如何检查对象是否正在@synchronized

时间:2013-07-01 03:10:06

标签: objective-c locking nonblocking synchronized

有时我编写以下代码来同步例程:

@synchronized(objToBeSync){ .... }

当两个线程同时尝试访问同步块时,会阻止其他线程,直到一个线程退出同步块。

然而,有时我不希望一个阻止另一个,但其他人检查对象是否正在同步,然后做一些其他事情所以我必须这样做:

@synchronized(objToBeSync){
    _isBeingSync = YES;
    ... 
    _isBeingSync = NO;
}

_isBeingSync是检查objToBeSync是否同步的额外变量。其他线程在继续工作之前检查_isBeingSync。我的问题是objc提供了直接检查objToBeSync但没有引入额外的var来标记其状态。

1 个答案:

答案 0 :(得分:5)

编译器将@synchronized(objToBeSync) { ... }转换为

callq   _objc_sync_enter
...
callq   _objc_sync_exit

来自 Objective-C Runtime Source Code(objc-sync.mm,objc-os.mm,objc-lockdebug.mm,objc-os.h)可以看出这些函数主要做了一个

pthread_mutex_lock(m->mutex);
...
pthread_mutex_unlock(m->mutex);

其中m->mutex是具有pthread_mutex_t属性的PTHREAD_MUTEX_RECURSIVE 与对象objToBeSync关联,使用运行时内部的缓存。

因此,您问题的直接答案是:不,没有公共API可以获得 对象的“锁定”状态,访问内部互斥锁对我来说几乎是不可能的。

因此,如果您有此要求,则应使用不同的锁定机制, 例如Posix互斥锁,NSLockNSRecursiveLock。所有这些锁具有 “try”方法,可用于获取锁定,或立即失败而不会阻塞。

请参阅 "Threading Programming Guide: Synchronization"了解概述。

注意@synchronized(与其他锁定机制相反)隐式地向块添加异常处理程序,以便 如果抛出异常,则释放互斥锁。

同样@synchronized是一个递归锁,即相同的线程可以进入受保护的 代码没有阻塞。如果这与您的代码相关,则必须使用 NSRecursiveLock或具有“递归”属性的Posix互斥锁。

请注意,为此目的使用简单的实例变量_isBeingSync是主题 竞争条件,不会安全。