锁
OSSpinLock
1. OSSpinLock叫做 "自旋锁",等待锁的线程会处于忙等(busy-wait)状态,一直占用着CPU资源
2. 目前已经不再安全,可能会出现优先级反转问题
3. 如果等待锁的线程优先级较高,它会一直占用着CPU资源,优先级低的线程就无法释放锁
4. 需要导入头文件#import <libkern/OSAtomic.h>
//初始化锁
OSSpinLock lock = OS_SPINLOCK_INIT;
/尝试加锁(如果需要等待就不加锁,直接返回false;如果不需要等待就加锁,返回true)
bool result = OSSpinLockTry(&lock);
//加锁
OSSpinLockLock(&lock);
//解锁
OSSpinLockUnlock(&lock);
os_unfair_lock
1. os_unfair_lock用于取代不安全的OSSpinLock ,从iOS10开始才支持
2. 从底层调用看,等待os_unfair_lock锁的线程会处于休眠状态,并非忙等
3. 需要导入头文件#import <os/lock.h>
// 初始化锁
os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
// 尝试加锁
os_unfair_lock_trylock(&lock);
// 加锁
os_unfair_lock_lock(&lock);
// 解锁
os_unfair_lock_unlock(&lock);
pthread_mutex
1. mutex叫做 "互斥锁",等待锁的线程会处于休眠状态
2. 需要导入头文件#import <pthread.h>
/*
* Mutex type attributes
*/
#define PTHREAD_MUTEX_NORMAL 0
#define PTHREAD_MUTEX_ERRORCHECK 1
#define PTHREAD_MUTEX_RECURSIVE 2
#define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL
// 初始化锁的属性
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);
// 初始化锁
pthread_mutex_t mutex;
pthread_mutex_init(mutex, &attr);
// 尝试加锁
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 attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
// 初始化锁
pthread_mutex_t mutex;
pthread_mutex_init(mutex, &attr);
pthread_mutex 条件实现
// 初始化锁
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
// 初始化条件
pthread_cond_t condition;
pthread_cond_init(condition, NULL);
// 加锁
pthread_mutex_lock(&mutex);
// 解锁
pthread_mutex_unlock(&mutex);
// 等待条件 (进入休眠,放开mutex锁;被唤醒后,会再次对mutex加锁)
pthread_cond_wait(&condition, &mutex);
// 信号激活一个等待该条件的锁
pthread_cond_signal(&condition);
// 广播激活所有等待该条件的锁
pthread_cond_broadcast(&condition);
// 销相关毁资源
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&condition);
NSLock
是对 pthread_mutex 的封装
NSLocking协议
@protocol NSLocking
- (void)lock;
- (void)unlock;
@end
@interface NSLock : NSObject <NSLocking> {
- (BOOL)tryLock;
- (BOOL)lockBeforeDate:(NSDate *)limit;
@end
// 初始化
NSLock *lock = [[NSLock alloc] init];
NSRecursiveLock
是对 pthread_mutex递归实现 的封装
@interface NSRecursiveLock : NSObject <NSLocking> {
- (BOOL)tryLock;
- (BOOL)lockBeforeDate:(NSDate *)limit;
@end
// 初始化
NSRecursiveLock *recursiveLock = [[NSRecursiveLock alloc] init];
NSCondition
是对 pthread_mutex条件实现 的封装
@interface NSCondition : NSObject <NSLocking> {
- (void)wait;
- (BOOL)waitUntilDate:(NSDate *)limit;
- (void)signal;
- (void)broadcast;
@end
// 初始化
NSCondition *condition = [[NSCondition alloc] init];
NSConditionLock
是对NSCondition的进一步封装,可以设置具体的条件值
@interface NSConditionLock : NSObject <NSLocking> {
- (instancetype)initWithCondition:(NSInteger)condition;
@property (readonly) NSInteger condition;
- (void)lockWhenCondition:(NSInteger)condition;
- (BOOL)tryLock;
- (BOOL)tryLockWhenCondition:(NSInteger)condition;
- (void)unlockWithCondition:(NSInteger)condition;
- (BOOL)lockBeforeDate:(NSDate *)limit;
- (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit;
@end
// 初始化
NSConditionLock *conditionLock = [[NSConditionLock alloc] initWithCondition:1];
@synchronized
1. @synchronized是对mutex递归锁的封装
2. 源码查看:objc4中的objc-sync.mm文件
3. @synchronized(obj)内部会生成obj对应的递归锁,然后进行加锁、解锁操作
@synchronized(obj) {
// todo
}
信号量
dispatch_semaphore
1. semaphore叫做 "信号量"
2. 信号量的初始值,可以用来控制线程并发访问的最大数量
3. 信号量的初始值为1,代表同时只允许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(DISPATCH_QUEUE_SERIAL)
1. 直接使用GCD的串行队列,也是可以实现线程同步的
dispatch_queue_t queue = dispatch_queue_create("lock_queue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
// todo
});
性能比较
性能从高到低排序
- os_unfair_lock
- OSSpinLock
- dispatch_semaphore
- pthread_mutex
- dispatch_queue(DISPATCH_QUEUE_SERIAL)
- NSLock
- NSCondition
- pthread_mutex(recursive)
- NSRecursiveLock
- NSConditionLock
- @synchronized
读写线程安全
pthread_rwlock
等待锁的线程会进入休眠
#import "ViewController.h"
#import <pthread.h>
@interface ViewController ()
@property (assign, nonatomic) pthread_rwlock_t lock;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
pthread_rwlock_init(&_lock, NULL);
}
- (void)read {
pthread_rwlock_rdlock(&_lock);
// do read
pthread_rwlock_unlock(&_lock);
}
- (void)write
{
pthread_rwlock_wrlock(&_lock);
// do write
pthread_rwlock_unlock(&_lock);
}
- (void)dealloc
{
pthread_rwlock_destroy(&_lock);
}
@end
dispatch_barrier_async
1. 这个函数传入的并发队列必须是自己通过dispatch_queue_cretate创建的
2. 如果传入的是一个串行或是一个全局的并发队列,那这个函数便等同于dispatch_async函数的效果
dispatch_queue_t queue = dispatch_queue_create("rw_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
//do read
});
dispatch_barrier_async(queue, ^{
// do write
});