我想要做的是使用@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的理解有点模糊,但我认为这会将块提交到分派队列,以便异步执行并立即返回。这意味着,如果另一个线程在dataStructure仍在写入磁盘时通过我的@synchronized块,它将提交另一个块来运行并将新修改的dataStructure写入磁盘,但直到第一个dataStructure写入磁盘时才会启动。
我的想法正确吗?另外,是否会自动将设置更改为YES或NO,或者分派队列的序列化是否会确保不会同时将多个线程写入此文件?
谢谢!
发布于 2014-07-03 16:52:27
调度队列本身是线程安全的。换句话说,您可以将任务从系统上的任何线程提交到调度队列,而无需首先锁定或同步对该队列的访问。
//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-03 16:56:38
你至少需要同步对锁对象的写操作。这是因为异步块在@synchronized{ ... }的上下文之外执行。这意味着在写入数据时,其他东西可能会更改数据,这可能会导致逻辑不一致。
您可能还需要一些机制来检查对象自上次写入以来是否已被修改。否则,您会发现自己正在进行不必要的IO操作。例如:
https://stackoverflow.com/questions/24548888
复制相似问题