有时我编写以下代码来同步例程:
@synchronized(objToBeSync){ .... }
当两个线程同时尝试访问同步块时,会阻止其他线程,直到一个线程退出同步块。
然而,有时我不希望一个阻止另一个,但其他人检查对象是否正在同步,然后做一些其他事情所以我必须这样做:
@synchronized(objToBeSync){
_isBeingSync = YES;
...
_isBeingSync = NO;
}
_isBeingSync
是检查objToBeSync是否同步的额外变量。其他线程在继续工作之前检查_isBeingSync
。我的问题是objc提供了直接检查objToBeSync但没有引入额外的var来标记其状态。
答案 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互斥锁,NSLock
或NSRecursiveLock
。所有这些锁具有
“try”方法,可用于获取锁定,或立即失败而不会阻塞。
请参阅 "Threading Programming Guide: Synchronization"了解概述。
注意@synchronized
(与其他锁定机制相反)隐式地向块添加异常处理程序,以便
如果抛出异常,则释放互斥锁。
同样@synchronized
是一个递归锁,即相同的线程可以进入受保护的
代码没有阻塞。如果这与您的代码相关,则必须使用
NSRecursiveLock
或具有“递归”属性的Posix互斥锁。
请注意,为此目的使用简单的实例变量_isBeingSync
是主题
竞争条件,不会安全。