7

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

@synchronized(objToBeSync){ .... }

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

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

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

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

4

1 回答 1

7

编译器翻译@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->mutexapthread_mutex_t具有PTHREAD_MUTEX_RECURSIVE与 object 关联的属性objToBeSync,使用运行时内部的缓存。

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

因此,如果您有此要求,您应该使用不同的锁定机制,例如 Posix 互斥锁NSLockNSRecursiveLock. 所有这些锁都有一个“try”方法,可以用来获取锁,或者立即失败而不阻塞。

有关概述,请参阅 “线程编程指南:同步” 。

请注意@synchronized(与其他锁定机制相比)隐式将异常处理程序添加到块中,以便在抛出异常时释放互斥锁。

同样@synchronized递归锁,即同一个线程可以不阻塞地进入受保护的代码。如果这与您的代码相关,您将不得不使用 NSRecursiveLock或带有“递归”属性的 Posix Mutex Lock。

请注意,_isBeingSync为此目的使用简单的实例变量会受到竞争条件的影响,并且不会安全地工作。

于 2013-07-01T07:34:07.363 回答