[英]@synchronized and dispatch_async
What I'm trying to do is to use the @synchronized
directive to protect a singleton object from being accessed by multiple threads at once. 我想做的是使用@synchronized
指令来保护单个对象不被多个线程一次访问。 I also want to persistently store that singleton object by writing it to disk after each time it's modified, because it is very important that I try as hard as possible not to lose any changes to the object. 我还想通过在每次修改后将其写入磁盘来持久存储该单例对象,因为尽我最大努力不丢失对该对象的任何更改非常重要。
Now I know a lot of you might say don't do that; 现在我知道你们中很多人可能会说不要这样做; it takes too long; 需要太长时间 it's not a good practice, etc., etc. Yes, I am aware of that. 这不是一个好习惯,等等。是的,我知道这一点。 This is more of a "what will happen?" 这更像是“将会发生什么?” question. 题。
So whenever I go to modify the singleton object, I put the modification code inside a @synchronized
block and then write the object to disk. 因此,每当我去修改单例对象时,我都会将修改代码放在@synchronized
块中,然后将该对象写入磁盘。 A thought I had was to use dispatch_async
to do the writing of the object on a separate thread like so: 我当时的想法是使用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];
});
}
So my understanding of @synchronized
is that only one thread can execute that block of code at a time. 因此,我对@synchronized
理解是,一次只有一个线程可以执行该代码块。 My understanding of dispatch_async
is a little fuzzy, but I think that this will submit the block to the dispatch queue to be executed asynchronously and return immediately. 我对dispatch_async
理解有些模糊,但是我认为这会将块提交到调度队列以异步执行并立即返回。 This means that if another thread comes through my @synchronized
block while dataStructure
is still being written to disk, it will just submit another block to run and write the newly modified dataStructure
to disk, but that won't start until the first dataStructure
is written to disk. 这意味着,如果另一个线程来通过我@synchronized
块,而dataStructure
仍然被写入到磁盘,它只是提出另一块运行并写入新修改的dataStructure
到磁盘上,但不会开始,直到第一个dataStructure
被写入到磁盘。
Am I thinking about this correctly? 我在想这个吗? Also will setting atomically change to YES
or NO
or will the serialization of my dispatch queue ensure that multiple threads won't be written to this file at the same time? 还会将原子设置更改为YES
或NO
还是将我的调度队列的序列化确保不会将多个线程同时写入此文件?
Thank you! 谢谢!
https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html
Dispatch queues themselves are thread safe. 调度队列本身是线程安全的。 In other words, you can submit tasks to a dispatch queue from any thread on the system without first taking a lock or synchronizing access to the queue. 换句话说,您可以从系统上的任何线程将任务提交到调度队列,而无需先获取锁或同步对该队列的访问。
//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];
});
}
You at least need to synchronise the write on the lock object. 您至少需要同步锁对象上的写入。 This is because the asynchronous block executes outside of the context of the @synchronized{ ... }
. 这是因为异步块在@synchronized{ ... }
的上下文之外执行。 This means that something else can change the data while it is being written which can lead to a logical inconsistency. 这意味着在写入数据时,其他某些事情可能会更改数据,这可能导致逻辑上的不一致。
You probably also want some mechanism to check if the object has been modified since it was last written. 您可能还需要某种机制来检查对象自上次写入以来是否已被修改。 Otherwise, you'll find yourself doing unnecessary IO operations. 否则,您会发现自己在执行不必要的IO操作。 eg 例如
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.