What are the common locks in iOS?

@synchronized, dispatch_semaphore_t, OS_UNfair_lock, implement several CLASSES of NSLocking (NSLock, NSRecursiveLock, NSCondition, NSConditionLock)

All of the above are mutex (that is, when a thread tries to access a shared resource and finds a lock, it sleeps and waits to wake up).

About lock performance

There are many articles on the web that discuss locking performance, but I don’t think this is necessary.

The first is certainly simple function, the more close to the bottom of the lock performance is the highest.

For example, a lock that implements recursion must perform better than a lock that does not implement recursion.

But isn’t it kind of boring to talk about performance without features?

Secondly, the online demo is all in a for loop, lock first and then unlock, without taking into account the case of multi-threading.

I don’t know if the performance comparisons are meaningful.

Took the demo online and ran it.

At 10,000 cycles, you can see that the performance of each lock does not differ much. The best differs from the worst by more than 300 milliseconds.

Therefore, I feel that in the daily development process, we can not consider the performance of the lock and focus on the implementation of the function.

A brief introduction to locks

@synchronized

The code used is generally as follows:

@synchronized** ( self ) {
   // do something
}
Copy the code

Very powerful. Data security can be ensured in multiple threads, while also supporting recursive use.

The internal implementation flow looks like this (regardless of caching) :

  • Before locking, try to fetch data from the thread’s TLS storage space

  • If the data exists and the lock id is the same as the current lock id, then the current thread already has a lock, increment the lockCount, and end the process to mutex lock.

  • There is no data or the lock identifier is inconsistent.

  • If there is no data, create data directly and increment threadCount by 1 to end the process and perform mutex lock.

  • If there is a data, but the identity of the lock is inconsistent, create a new data, insert it into the head of the list, end the process, and perform the mutex lock.

NSLock

Is a relatively simple mutex.

Note when using:

  • Recursion is not supported, that is, the same thread cannot be locked before it is unlocked.

  • Lock and unlock operations must be performed on the same thread

NSRecursiveLock/ pthread_mutex(recursive)

Can achieve recursive locking function.

NSCondition / NSConditionLock

Conditions can be added to locks.

NSConditionThe use of:

NSConditionLockUse as follows:You can see whenconditionIf not, the current thread of execution is stuck until the condition is met.

dispatch_semaphore

Dispatch_semaphore_wait (dispatch_semaphore_t dsema, dispatch_time_t timeout); And dispatch_semaphore_signal (dispatch_semaphore_t dsema); To achieve the effect of the lock.

If the value of dispatch_semaphoRE_wait is less than zero, the thread will be stuck waiting to wake up. If the value of dispatch_semaphore_wait is less than zero, the thread will be woken up.

os_unfair_lock

Used to replace OSSpinLock, which has been deprecated due to priority inversion.

OSSpinLock deprecated for:

High-priority threads always execute before low-priority threads. If a lower-priority thread is the first to acquire the lock and access the shared resource, and the higher-priority thread tries to acquire the lock, the higher-priority thread is waiting for the lock, while the lower-priority thread is waiting for the higher-priority thread to run out of CPU

Os_unfair_lock is a mutex and OSSpinLock is a spin lock.

Read-write lock

A long time ago, I remember an interview question, the interviewer asked me to achieve:

  • Only one thread can do setter operations at a time;

  • Multiple threads are allowed to perform getter operations at the same time.

  • Setter and getter operations are mutually exclusive at the same time;

Not long ago, I saw a video and realized that this is an actual scenario of a read/write lock.

The solution is to use the fence function