objective-c - 锁定一个对象不被多个线程访问 - Objective-C

标签 objective-c ios multithreading

我对 Objective-C 中的线程安全有疑问。我已经阅读了其他几个答案,一些 Apple 文档,但对此仍有一些疑问,所以我想问我自己的问题。

我的问题是三折:

假设我有一个数组,NSMutableArray *myAwesomeArray;

折叠 1:

如果我弄错了,现在纠正我,但据我了解,使用 @synchronized(myAwesomeArray){...} 将阻止两个线程访问同一代码块。所以,基本上,如果我有类似的东西:

-(void)doSomething {
    @synchronized(myAwesomeArray) {
        //some read/write operation on myAwesomeArray
    }
}

那么,如果两个线程在same 时间访问same 方法,那么该代码块将是线程安全的。我猜我已经正确理解了这部分。

折叠 2:

如果 myAwesomeArray 正被多个线程从不同的方法访问,我该怎么办? 如果我有类似的东西:

- (void)readFromArrayAccessedByThreadOne {
    //thread 1 reads from myAwesomeArray
}

- (void)writeToArrayAccessedByThreadTwo {
    //thread 2 writes to myAwesomeArray
}

现在,两个不同的线程同时访问这两种方法。如何确保 myAwesomeArray 不会出现问题?我是否使用 NSLock 或 NSRecursiveLock 之类的东西?

3 折:

现在,在上述两种情况下,myAwesomeArray 是内存中的 iVar。如果我有一个数据库文件,我并不总是保存在内存中怎么办。每当我想执行数据库操作时,我都会创建一个 databaseManagerInstance ,并在完成后释放它。因此,基本上,不同的类可以访问数据库。每个类都创建自己的 DatabaseManger 实例,但基本上,它们都使用相同的单一数据库文件。在这种情况下,如何确保数据不会因竞争条件而损坏?

这将帮助我理清一些基础知识。

最佳答案

折叠 1 一般来说,您对 @synchronized 所做的事情的理解是正确的。但是,从技术上讲,它不会使任何代码“线程安全”。它可以防止不同的线程同时获取相同的锁,但是您需要确保在执行关键部分时始终使用相同的同步 token 。如果你不这样做,你仍然会发现自己处于两个线程同时执行临界区的情况。 Check the docs .

折叠 2 大多数人可能会建议您使用 NSRecursiveLock。如果我是你,我会使用 GCD。 Here is a great document showing how to migrate from thread programming to GCD programming ,我认为这种解决问题的方法比基于 NSLock 的方法要好得多。简而言之,您创建一个串行队列并将您的任务分派(dispatch)到该队列中。这样可以确保您的关键部分是按顺序处理的,因此在任何给定时间只执行一个关键部分。

3折 这与 Fold 2 相同,只是更具体。数据库是一种资源,在许多方面它与数组或任何其他东西相同。 If you want to see the GCD based approach in database programming context, take a look at fmdb implementation .它完全符合我在 Fold2 中描述的功能。

作为 Fold 3 的附注,我不认为每次要使用数据库时都实例化 DatabaseManager 然后释放它是正确的方法。我认为您应该创建一个单一的数据库连接并通过您的应用程序 session 保留它。这样更容易管理它。同样,fmdb 是一个很好的例子,说明了如何实现这一点。

编辑 如果不想使用 GCD,那么是的,您将需要使用某种锁定机制,是的,如果您在方法中使用递归,NSRecursiveLock 将防止死锁,所以这是一个不错的选择(它由 @synchronized 使用)。但是,可能有一个问题。如果许多线程可能会等待相同的资源并且它们获得访问的顺序是相关的,那么 NSRecursiveLock 是不够的。您仍然可以使用 NSCondition 来处理这种情况,但相信我,在这种情况下使用 GCD 会节省大量时间。如果线程的顺序不相关,则使用锁是安全的。

关于objective-c - 锁定一个对象不被多个线程访问 - Objective-C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10853529/

相关文章:

ios - 在 ios 应用程序中合并两个视频仍然保持每个视频的方向?

iphone - 如何在 iphone 中检测麦克风的打击而不是语音?

iphone - 无法识别触摸导航栏的 ImageView 。?

ios - RXSwift flatMap 两种方法

ios - 为什么 PHAsset fetchAssetsWithOptions 不返回所有 Assets ?

ios - 新 Alamofire Swift 3 上的 GET 请求

perl - 为什么这个特定 Perl 脚本的线程版本比非线程版本慢 200 倍?

iphone - 从 FQL 中的用户表获取个人资料图片创建日期

vb.net - VB.NET 中从另一个线程挂起一个线程

C# - 作为执行异步任务的委托(delegate),我仍然需要 System.Threading 吗?