1

我要做的是使用该@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有点模糊,但是我认为这样会将block提交到dispatch queue中异步执行并立即返回。这意味着如果另一个线程在写入磁盘@synchronized时通过我的块dataStructure,它只会提交另一个块来运行并将新修改的写入磁盘,但是直到第一个写入磁盘后dataStructure才会开始。dataStructure

我是否正确地考虑了这一点?也将设置原子地更改YESNO或将我的调度队列的序列化确保多个线程不会同时写入该文件?

谢谢!

4

2 回答 2

0

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

}
于 2014-07-03T08:52:27.123 回答
0

您至少需要同步锁定对象上的写入。这是因为异步块在@synchronized{ ... }. 这意味着其他东西可以在写入数据时更改数据,这可能导致逻辑不一致。

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

  • 线程 1 修改对象并将写入写入队列。
  • 线程 2 修改对象并将写入写入队列。
  • 线程 1 的写入保存了线程 1 和线程 2 的 mod
  • 线程 2 的写入保存线程 1 和线程 2 的 mods(与上一步相同)
于 2014-07-03T08:56:37.930 回答