How do I check if an object is being @synchronized

2020-07-13 11:45发布

Sometimes I wrote the following code to synchronized a routine:

@synchronized(objToBeSync){ .... }

When two threads try to access the sync block at the same time, one will block the others, until the one exits the sync block.

However, sometimes I don't want one blocks the other, but the others check if the object is being synchronized, and then do some other thing so I have to do sth like this:

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

_isBeingSync is an additional var on checking if objToBeSync is being sync. The other threads check _isBeingSync before they continue their work. And my question is that does objc provide sth to check objToBeSync directly but not introduce an additional var to mark down its status.

1条回答
男人必须洒脱
2楼-- · 2020-07-13 12:13

The compiler translates @synchronized(objToBeSync) { ... } into

callq   _objc_sync_enter
...
callq   _objc_sync_exit

and from the Objective-C Runtime Source Code (objc-sync.mm, objc-os.mm, objc-lockdebug.mm, objc-os.h) one can see that these functions mainly do a

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

where m->mutex is a pthread_mutex_t with the PTHREAD_MUTEX_RECURSIVE attribute that is associated with the object objToBeSync, using a cache internal to the runtime.

So the direct answer to your question is: No, there is no public API to get the "locked" status of an object, and accessing the internal mutex seems almost impossible to me.

Therefore, you should use a different locking mechanism if you have that requirement, e.g. a Posix Mutex Lock, NSLock or NSRecursiveLock. All these locks have a "try" method that can be used to aquire the lock, or fail immediately without blocking.

See "Threading Programming Guide: Synchronization" for an overview.

Note that @synchronized (in contrast to the other locking mechanisms) implicitly adds an exception handler to the block so that the mutex is released if an exception is thrown.

Also @synchronized is a recursive lock, i.e. the same thread can enter the protected code without blocking. If that is relevant to your code, you would have to use NSRecursiveLock or a Posix Mutex Lock with the "recursive" attribute.

Note that using a simple instance variable _isBeingSync for this purpose is subject to race conditions and will not work safely.

查看更多
登录 后发表回答