我要做的是使用@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
写入磁盘之前不会启动。
我是否正确地考虑过这个问题?还会将原子设置更改为YES
或NO
,或者我的调度队列的序列化是否确保多个线程不会同时写入此文件?
谢谢!
答案 0 :(得分:0)
Dispatch队列本身是线程安全的。换句话说,您可以从系统上的任何线程向调度队列提交任务,而无需先锁定或同步对队列的访问。
//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];
});
}
答案 1 :(得分:0)
您至少需要同步锁定对象上的写入。这是因为异步块在@synchronized{ ... }
的上下文之外执行。这意味着其他东西可以在写入时改变数据,这可能导致逻辑上的不一致。
您可能还需要一些机制来检查对象自上次写入以来是否已被修改。否则,您将发现自己正在进行不必要的IO操作。例如