iOS thread lock ##### 1: Ten thread locks

1: Ten thread locks

  • When we use multithreading, multiple threads may access the same resource, which can easily lead to problems such as data disorder and data security. At this time, we need to ensure that only one thread accesses this resource at a time, and the lock arises at the historic moment.
  • By the way, there are two locking methods, trylock and lock usage scenarios: undefined. If the lock of the current thread fails, you can continue other tasks. Trylock is suitable for undefined. The current thread will do some meaningful work only after the lock succeeds. Then lock. There is no need to poll trylock

Here are ten thread locks:

image.png

1. OSSpinLock (spin lock)

The most efficient lock in the test, but the author of YYKit confirmed that OSSpinLock is no longer thread safe, and OSSpinLock has a potential priority reversal problem

Header files need to be imported
#import <libkern/OSAtomic.h>
// initialization
OSSpinLock spinLock = OS_SPINLOCK_INIT;
// Lock
OSSpinLockLock(&spinLock);
// Unlock
OSSpinLockUnlock(&spinLock);
// Try to lock. If you can lock, lock immediately and return YES. Otherwise, return NO
OSSpinLockTry(&spinLock)
/*
notes:Apple's father is already there iOS10.0 Later, this locking mechanism was abandoned,use os_unfair_lock replace,
As the name suggests, it can ensure that the priority reversal problem will not occur when threads with different priorities apply for locks.
*/
2,os_ unfair_ Lock (mutex lock)
Header files need to be imported
#import <os/lock.h>
// initialization
os_unfair_lock unfair_lock = OS_UNFAIR_LOCK_INIT;
// Lock
os_unfair_lock_lock(&unfair_lock);
// Unlock
os_unfair_lock_unlock(&unfair_lock);
// Try to lock. If you can lock, lock immediately and return YES. Otherwise, return NO
os_unfair_lock_trylock(&unfair_lock);
/*
notes:Solve the problem of no priority reversal when threads with different priorities apply for locks.
But relative to OSSpinLock , os_unfair_lock The performance is weakened a lot.
*/
3,dispatch_semaphore
// initialization
dispatch_semaphore_t semaphore_t = dispatch_semaphore_create(1);
// Lock
dispatch_semaphore_wait(semaphore_t,DISPATCH_TIME_FOREVER);
// Unlock
dispatch_semaphore_signal(semaphore_t);
/*
notes: dispatch_semaphore  Two other functions
1.It can also block threads.
2.Timer function can be realized,There is not much introduction here.
*/
4,pthread_ Mutex (mutex)
Header files need to be imported
#import <pthread/pthread.h>
// Initialization (both)
1.Normal initialization
pthread_mutex_t mutex_t;
pthread_mutex_init(&mutex_t, NULL); 
2.Macro initialization
pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER;
// Lock
pthread_mutex_lock(&mutex_t);
// Unlock
pthread_mutex_unlock(&mutex_t);
// When you try to lock, you will return 0 when you can lock, otherwise you will return an error
pthread_mutex_trylock(& mutex_t)
5. Nslock (mutex, object lock)
// initialization
NSLock *_lock = [[NSLock alloc]init];
// Lock
[_lock lock];
// Unlock
[_lock unlock];
// Try to lock. If you can lock, lock immediately and return YES. Otherwise, return NO
[_lock tryLock];
6. Nscondition (condition lock, object lock)
// initialization
NSCondition *_condition= [[NSCondition alloc]init];
// Lock
[_condition lock];
// Unlock
[_condition unlock];
/*
Other functional interfaces
wait Enter the waiting state
waitUntilDate:Let a thread wait for a certain time
signal Wake up a waiting thread
broadcast Wake up all waiting threads
notes: The measured time fluctuates too much, Sometimes faster than NSLock, I get the middle value.
*/
7. Nsconditionlock (condition lock, object lock)
// initialization
NSConditionLock *_conditionLock = [[NSConditionLock alloc]init];
// Lock
[_conditionLock lock];
// Unlock
[_conditionLock unlock];
// Try to lock. If you can lock, lock immediately and return YES. Otherwise, return NO
[_conditionLock tryLock];
/*
Other functional interfaces
- (instancetype)initWithCondition:(NSInteger)condition NS_DESIGNATED_INITIALIZER; //Initialize incoming conditions
- (void)lockWhenCondition:(NSInteger)condition;//Trigger lock when condition holds
- (BOOL)tryLockWhenCondition:(NSInteger)condition;//Trigger lock when the attempt condition is true
- (void)unlockWithCondition:(NSInteger)condition;//Unlock when conditions are satisfied
- (BOOL)lockBeforeDate:(NSDate *)limit;//Trigger lock within waiting time
- (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit;//The trigger lock condition is true and within the waiting time
*/
8. Nsrecursivelock (recursive lock, object lock)
// initialization
NSRecursiveLock *_recursiveLock = [[NSRecursiveLock alloc]init];
// Lock
[_recursiveLock lock];
// Unlock
[_recursiveLock unlock];
// Try to lock. If you can lock, lock immediately and return YES. Otherwise, return NO
[_recursiveLock tryLock];
/*
notes: A recursive lock can be requested multiple times by the same thread without causing a deadlock.
That is, it can be locked in the same thread before unlocking, Execute the code in the lock.
This is mainly used in loop or recursive operations.
- (BOOL)lockBeforeDate:(NSDate *)limit;//Trigger lock within waiting time
*/
9. @ synchronized() recursive lock
// initialization
@synchronized(Lock object){
}
Bottom encapsulated pthread_mutex of PTHREAD_MUTEX_RECURSIVE pattern,
Lock object to indicate whether it is the same lock
10,pthread_ Mutex (recursive)
// initialization
pthread_mutex_t mutex_t;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr); //Initialize attr and give it a default pthread_ mutexattr_ settype(&attr, PTHREAD_MUTEX_RECURSIVE); // Set the lock type. Here is the recursive lock
pthread_mutex_init(&mutex_t, &attr);
pthread_mutexattr_destroy(&attr); //Destroy a property object. The structure cannot be reused until it is reinitialized
// Lock
pthread_mutex_lock(&mutex_t);
// Unlock
pthread_mutex_unlock(&mutex_t);
/*
notes: A recursive lock can be requested multiple times by the same thread without causing a deadlock.
That is, it can be locked in the same thread before unlocking, Execute the code in the lock.
This is mainly used in loop or recursive operations.
*/

2: Type of lock

1. Spin lock

OSSpinLock is a typical spin lock

The spin lock is characterized by that when the lock is not obtained, the lock has been added and has not been unlocked. The OSSpinLock is busy and always occupies CPU resources, similar to the following pseudo code:

while(The lock is not unlocked);

On priority inversion

Due to thread scheduling, the allocation time weight of each thread is different. The threads with low weight first enter the OSSpinLock and give priority to locking, and the threads with high weight will access again. It is blocked here. The threads with high weight may be allocated to the cpu all the time, so they will come in all the time. However, because there is a lock, they can only wait, and the threads with low weight cannot get cpu resource allocation, so they will not be unlocked, Cause a certain degree of deadlock

2. Mutex

os_unfair_lock ,pthread_mutex is a typical mutex. When the lock is not obtained, it is added and not unlocked

Both of them will put the current thread into sleep, which does not occupy CPU resources. However, why is mutex less efficient than spin lock? It is because sleep and wake-up sleep consume more CPU resources than busy

NSLock encapsulated pthread_ Pthread of mutex_ MUTEX_ Normal mode

NSRecursiveLock encapsulated pthread_ Pthread of mutex_ MUTEX_ Recursive mode

3. Conditional lock

Under certain conditions, let it wait for sleep and unlock it. When a signal or broadcast is received, the thread will be recalled and locked again

pthread_cond_wait(&_cond, &_mutex);
// signal
pthread_cond_signal(&_cond);
// radio broadcast
pthread_cond_broadcast(&_cond);

Like NSCondition, it encapsulates pthread_ The above functions of mutex, NSConditionLock encapsulates NSCondition

4. Recursive lock

The main meaning of recursive lock is that the same thread can add more locks. What does it mean? The same thread accesses a piece of code. If it is locked, it can continue to add locks and continue to go down. When different threads access this piece of code, they find that there are locks and wait for all locks to be released before they can continue to go down

NSRecursiveLock encapsulated pthread_ Pthread of mutex_ MUTEX_ Recursive mode

Posted on Sun, 21 Nov 2021 21:28:23 -0500 by TeddyKiller