One: Ten thread locks

  • When we use multithreading, multiple threads may access the same resource, which is easy to cause problems such as data disorder and data security. At this time, we need to ensure that only one thread accesses the resource at a time, and lock arises.
  • By the way, there are two ways to lock trylock and lock use scenarios:

If trylock fails, the thread can continue with other tasks. Trylock is suitable for the thread. If trylock succeeds, the thread will do some meaningful work

Here are the elapsed times for the ten thread locks:

1. OSSpinLock

The most efficient lock in the test, but YYKit authors confirmed that OSSpinLock is no longer thread safe,OSSpinLock has a potential priority inversion problem

#import <libkern/OSAtomic. H > // initialize OSSpinLock spinLock = OS_SPINLOCK_INIT; / / lock OSSpinLockLock (& spinLock); / / unlock OSSpinLockUnlock (& spinLock); // Try to lock, NO OSSpinLockTry(&spinLock) /* */ * * * * * * * * * * * * * *Copy the code

2. Os_unfair_lock (mutex)

#import < OS /lock.h> // Initialize os_unfair_LOCK unfair_LOCK = OS_UNFAIR_LOCK_INIT; / / lock os_unfair_lock_lock (& unfair_lock); / / unlock os_unfair_lock_unlock (& unfair_lock); // Os_unfair_lock_trylock (&unfair_lock); // Os_unfair_trylock (&unfair_lock); // Os_unfair_trylock (& unfair_trylock); /* Note: Resolve the priority reversal problem when threads with different priorities apply for locks. However, compared with OSSpinLock, OS_UNfair_LOCK performance is significantly reduced. */Copy the code

3. Dispatch_semaphore

// Initialize dispatch_semaphore_t semaphore_t = dispatch_semaphore_create(1); / / lock dispatch_semaphore_wait (semaphore_t DISPATCH_TIME_FOREVER); / / unlock dispatch_semaphore_signal (semaphore_t); /* Note: the other two functions of dispatch_semaphore 1. It can also block the thread. 2. It can implement the timer function, which will not be introduced hereCopy the code

4. Pthread_mutex

#import <pthread/pthread.h> // initialize (both) 1. Normal initialization pthread_mutex_t mutex_t; pthread_mutex_init(&mutex_t, NULL); 2. Macro pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER; / / lock pthread_mutex_lock (& mutex_t); / / unlock pthread_mutex_unlock (& mutex_t); Pthread_mutex_trylock (& mutex_t)Copy the code

5, NSLock(mutex, object lock)

// Initialize NSLock *_lock = [[NSLock alloc]init]; // Add lock [_lock lock]; // Unlock [_lock unlock]; Return NO [_lock tryLock]; return NO [_lock tryLock];Copy the code

NSCondition(condition lock, object lock)

// Initialize NSCondition *_condition= [[NSCondition alloc]init]; // Lock [_condition lock]; [_condition unlock]; Signal to wake up a waiting thread. Broadcast to wake up all waiting threads. The measured time fluctuates too much, sometimes faster than NSLock, and I get the median. */Copy the code

NSConditionLock(NSConditionLock)

// Initialize NSConditionLock *_conditionLock = [[NSConditionLock alloc]init]; [_conditionLock lock]; [_conditionLock unlock]; Return NO [_conditionLock tryLock]; return NO [_conditionLock tryLock]; /* other function interfaces - (instancetype)initWithCondition:(NSInteger)condition NS_DESIGNATED_INITIALIZER; // Initialize the passed condition - (void)lockWhenCondition (NSInteger)condition; (BOOL)tryLockWhenCondition:(NSInteger)condition; - (void)unlockWithCondition:(NSInteger)condition; // conditional unlock - (BOOL)lockBeforeDate:(NSDate *)limit; // trigger lock within wait time - (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit; // The trigger lock condition is valid and within the waiting time */Copy the code

NSRecursiveLock

// Initialize NSRecursiveLock *_recursiveLock = [[NSRecursiveLock alloc]init]; [_recursiveLock lock]; [_recursiveLock unlock]; Return NO [_recursiveLock tryLock]; return NO [_recursiveLock tryLock]; /* Note: a recursive lock can be requested multiple times by the same thread without causing a deadlock. That is, in the same thread before unlocking can also be locked, the code in the lock. This is mostly used for looping or recursive operations. - (BOOL)lockBeforeDate:(NSDate *)limit; // Trigger the lock within the waiting time */Copy the code

9, @synchronized(

// initializes @synchronized {} the PTHREAD_MUTEX_RECURSIVE mode of the underlying pthread_mutex, which locks the object to indicate whether it is the same lockCopy the code

10, pthread_mutex(recursive)

// Initialize pthread_mutex_t mutex_t; pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); // Initialize attr and give it the default pthread_mutexattr_setType (&attr, PTHREAD_MUTEX_RECURSIVE); Pthread_mutex_init (&mutex_t, &attr); pthread_mutexattr_destroy(&attr); Pthread_mutex_lock (&mutex_t); // Pthread_mutex_lock (&mutex_t); / / unlock pthread_mutex_unlock (& mutex_t); /* Note: a recursive lock can be requested multiple times by the same thread without causing a deadlock. That is, in the same thread before unlocking can also be locked, the code in the lock. This is mostly used for looping or recursive operations. * /Copy the code

Two: lock type

1. Spin lock

OSSpinLock is a characteristic of spin-lock that is not acquired when the lock has been added, but has not been unlocked. OSSpinLock is busy and occupies CPU resources, as shown in the following pseudocode:

While (the lock is not unlocked);Copy the code

About priority inversion Due to thread scheduling, each thread weight is not the same time, the distribution of the weights when small thread into OSSpinLock priority lock, in serious thread to access again, just block in this, heavy thread may have been assigned to the CPU so always will come in, but because of the lock, can only wait for, weight small thread can not get the CPU resource allocation, the Will not unlock, resulting in a certain degree of deadlock.

2. Mutex

Os_unfair_lock and pthread_mutex are typical mutex locks that are added but ununlocked when they are not acquired. Both of them put the current thread into hibernation without consuming CPU resources, but the reason why a mutex is less efficient than a spin lock is that hibernation, and waking up hibernation, consumes more CPU resources than busy and so on.

PTHREAD_MUTEX_NORMAL mode of pthread_mutex wrapped by NSLock PTHREAD_MUTEX_RECURSIVE mode of pthread_mutex wrapped by NSRecursiveLock

3. Conditional locking

Under certain conditions, let it wait for sleep, and release the lock, and when receiving a signal or broadcast, the thread will be awakened, and re-lock.

pthread_cond_wait(&_cond, &_mutex); / / signal pthread_cond_signal (& _cond); / / radio pthread_cond_broadcast (& _cond); Just as NSCondition encapsulates the above functions of pthread_mutex, NSConditionLock encapsulates NSConditionCopy the code

4. Recursive locks

The main idea behind recursive locking is that the same thread can add multiple locks. What does it mean? It means that the same thread accesses a piece of code, and if it is locked, it can continue to lock, and continue to go down. When different threads access this piece of code, they find that there is a lock, and they have to wait for all the locks to be unlocked before they can continue to go down.

NSRecursiveLock encapsulates the PTHREAD_MUTEX_RECURSIVE mode of pthread_mutex

The original address: www.jianshu.com/p/74702b6b8…