首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >@synchronized和dispatch_async

@synchronized和dispatch_async
EN

Stack Overflow用户
提问于 2014-07-03 16:39:34
回答 2查看 638关注 0票数 1

我想要做的是使用@synchronized指令来保护一个单例对象,防止它同时被多个线程访问。我还希望通过在每次修改后将其写入磁盘来持久地存储该单例对象,因为尽可能不丢失对该对象的任何更改是非常重要的。

现在我知道你们中的很多人可能会说不要这样做;这需要太长时间;这不是一个好的实践,等等。是的,我知道这一点。这更像是一个“会发生什么?”有个问题。

因此,每当我要修改单例对象时,我都会将修改代码放入@synchronized块中,然后将该对象写入磁盘。我的一个想法是使用dispatch_async在单独的线程上编写对象,如下所示:

代码语言:javascript
复制
//singleton object
id dataStructure;

@synchronized(lockObject)
    {
        //code that modifies singleton object
        //not important

        //sharedFileQueue is a SERIAL queue
        dispatch_async([self sharedFileQueue], ^(void){
            NSError * err;

            NSData * plist = [NSPropertyListSerialization dataWithPropertyList:dataStructure
                                                      format:NSPropertyListBinaryFormat_v1_0
                                                      options:0 error:&err];

            //url to somewhere
            NSURL * url;
            BOOL success = [plist writeToURL:url atomically:YES];
        });

    }

因此,我对@synchronized的理解是,一次只能有一个线程执行该代码块。我对dispatch_async的理解有点模糊,但我认为这会将块提交到分派队列,以便异步执行并立即返回。这意味着,如果另一个线程在dataStructure仍在写入磁盘时通过我的@synchronized块,它将提交另一个块来运行并将新修改的dataStructure写入磁盘,但直到第一个dataStructure写入磁盘时才会启动。

我的想法正确吗?另外,是否会自动将设置更改为YESNO,或者分派队列的序列化是否会确保不会同时将多个线程写入此文件?

谢谢!

EN

回答 2

Stack Overflow用户

发布于 2014-07-03 16:52:27

https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

调度队列本身是线程安全的。换句话说,您可以将任务从系统上的任何线程提交到调度队列,而无需首先锁定或同步对该队列的访问。

代码语言:javascript
复制
//singleton object
id dataStructure;

@synchronized(lockObject)
{
    //code that modifies singleton object
    //not important

    id dataStructureToWrite = [dataStructure copy];
    //sharedFileQueue is a SERIAL queue
    dispatch_async([self sharedFileQueue], ^(void){
        NSError * err;

        NSData * plist = [NSPropertyListSerialization dataWithPropertyList:dataStructureToWrite
                                                                    format:NSPropertyListBinaryFormat_v1_0
                                                                   options:0 error:&err];

        //url to somewhere
        NSURL * url;
        BOOL success = [plist writeToURL:url atomically:YES];
    });

}
票数 0
EN

Stack Overflow用户

发布于 2014-07-03 16:56:38

你至少需要同步对锁对象的写操作。这是因为异步块在@synchronized{ ... }的上下文之外执行。这意味着在写入数据时,其他东西可能会更改数据,这可能会导致逻辑不一致。

您可能还需要一些机制来检查对象自上次写入以来是否已被修改。否则,您会发现自己正在进行不必要的IO操作。例如:

  • 线程1修改对象并将写操作放到队列上。
  • 线程2修改对象并将写入放入队列。
  • 线程1的写入保存线程1和线程2的mods。
  • 线程2的写入保存线程1和线程2的mods (与上一步相同)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24548888

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档