OC原理之多线程中的锁(一)
OSSpinLock
OSSpinLock叫做"自旋锁",等待锁的线程会处于忙等状态,一直占用着cpu资源。由于可能会出现优先级反转的问题,是个不安全锁。在iOS10苹果已经不推荐使用了
优先级反转问题
如果等待锁的线程优先级较高,它会一直占用着CPU资源,优先级低的线程就无法释放 使用的时候需要导入#import <libkern/OSAtomic.h>
使用代码
OSSpinLock lock = OS_SPINLOCK_INIT; bool result = OSSpinLockTry(lock);// 尝试加锁(如果需要等待就不加锁,直接返回false,如果不需要等待就加锁,返回true) OSSpinLockLock(lock); // 加锁 OSSpinLockUnlock(lock);// 不加锁
os_unfair_lock
os_unfair_lock用于取代不安全的OSSpinLock,iOS10以后才支持
相比较于OSSpinLock的区别,等待os_unfair_lock锁的线程会处于休眠状态,并非忙等
使用时,如要导入头文件#import <os/lock.h>
使用代码
os_unfair_lock lock = OS_UNFAIR_LOCK_INIT; bool result = os_unfair_lock_trylock(&lock); // 尝试加锁 返回值=是否加锁成功 os_unfair_lock_lock(&lock); // 加锁 os_unfair_lock_unlock(&lock); // 解锁
pthread_mutex
mutex叫做"互斥锁",等待锁的线程会处于休眠状态
需要导入头文件#import <pthread.h>
使用代码
// 初始化锁的属性 pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); // 初始化锁 pthread_mutex_t mutex; pthread_mutex_init(&mutex, &attr); // 尝试加锁 bool result = pthread_mutex_trylock(&mutex); // 加锁 pthread_mutex_lock(&mutex); // 解锁 pthread_mutex_unlock(&mutex); // 销毁相关资源 pthread_mutexattr_destroy(&attr); pthread_mutex_destroy(&mutex);
pthread_mutex - 递归锁
递归锁的话,创建方式与互斥锁的方式相同,只是在创建pthread_mutexattr_t的之后,设置类型为PTHREAD_MUTEX_RECURSIVE
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex – 条件
使用代码:
// 初始化锁 pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL); // 初始化条件 pthread_cond_t condition; pthread_cond_init(&condition, NULL); // 等待条件(进入休眠,放开mutex锁,被唤醒后,会再次对mutex加锁) pthread_cond_wait(&condition, &mutex); // 激活一个等待该条件的线程 pthread_cond_signal(&condition); // 激活所有等待该条件的线程 pthread_cond_broadcast(&condition); // 销毁 pthread_mutex_destroy(&mutex); pthread_cond_destroy(&condition);
NSLock
NSLock是对mutex普通锁的封装
NSRecursiveLock
NSrecursiveLock是对mutex递归锁的封装
NSCondition
NSCondition是对mutex和cond的封装
dispatch_semaphore
semaphore叫做"信号量"
信号量的初始值,可以用来控制线程并发访问的最大数量
信号量的初始值为1,代表同时只允许一条线程访问资源,保证线程同步
使用代码:
// 信号量的初始值 int value = 1; // 初始化信号量 dispatch_semaphore_t semaphore = dispatch_semaphore_create(value); // 如果信号量的值<=0,当前线程就会进入休眠等待(知道信号量的值>0) // 如果信号量的值>0,就减1,然后往下执行后面的代码 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); // 让信号量的值加1 dispatch_semaphore_signal(semaphore);
dispatch_queue
直接使用GCD的串行队列,也是可以显示线程同步的
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL); dispatch_sync(queue, ^{ });
@synchronized
@synchronized是对mutex递归锁的封装
源码查看:objc4中的objc-sync.mm文件
@synchronized(obj)内部会生成obj对应的递归锁,然后进行加锁、解锁操作
使用代码:
@synchronized (object) { }