繁体   English   中英

@synchronized和dispatch_async

[英]@synchronized and dispatch_async

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

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

因此,每当我去修改单例对象时,我都会将修改代码放在@synchronized块中,然后将该对象写入磁盘。 我当时的想法是使用dispatch_async在类似这样的单独线程上写对象:

//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理解有些模糊,但是我认为这会将块提交到调度队列以异步执行并立即返回。 这意味着,如果另一个线程来通过我@synchronized块,而dataStructure仍然被写入到磁盘,它只是提出另一块运行并写入新修改的dataStructure到磁盘上,但不会开始,直到第一个dataStructure被写入到磁盘。

我在想这个吗? 还会将原子设置更改为YESNO还是将我的调度队列的序列化确保不会将多个线程同时写入此文件?

谢谢!

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

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

//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];
    });

}

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

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

  • 线程1修改对象并将写入写入队列。
  • 线程2修改对象并将写入写入队列。
  • 线程1的写操作保存了线程1和线程2中的mod
  • 线程2的写操作保存了线程1和线程2中的mod(与最后一步相同)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM