参考 demo
参考的文章:
iOS开发中的11种锁以及性能对比
多线程-线程安全
结论:
- 自旋锁性能 > 信号量 > 互斥锁
- 等待互斥锁的线程会进行休眠状态避免继续占用CPU资源
- 互斥的实现涉及到了可能发生的内核态切换,线程休眠、唤醒等,如果临界执行代码足够小而快,不适合互斥锁
- 等待自旋锁的线程会进入while循环中空转等待
- 自旋的实现逻辑足够简单,只要标记位的修改被设计为原子操作,就能保证多线程环境下的安全。对比互斥方案,自旋没有线程切换、休眠唤醒的开销。但是空转的代码会导致CPU在等待期间是满负荷执行的,如果加锁的代码不够小而快,甚至会直接影响到程序的运行
互斥锁
- NSLock
//初始化
self.array = @[].mutableCopy;
self.lock = [[NSLock alloc] init];
self.lock.name = @"com.example.lock.nslock";
//多线程,访问临界区
[self.lock lock];
[self.array addObject:number];
[self.lock unlock];
- pthread_mutex_t
//头文件
#import <pthread.h>
//定义
pthread_mutex_t mutex;
//初始化
self.array = @[].mutableCopy;
pthread_mutex_init(&mutex,NULL);
//多线程,访问临界区
pthread_mutex_lock(&mutex);
[self.array addObject:number];
pthread_mutex_unlock(&mutex);
//dealloc
pthread_mutex_destroy(&mutex);
- @synchronized
@synchronized (self) {
[self.array addObject:number];
}
自旋锁
- OSSpinLock (废弃)
存在的问题,优先级反转:
如果一个低优先级的线程获得锁并访问共享资源,这时一个高优先级的线程也尝试获得这个锁,它会处于 spin lock 的忙等状态从而占用大量 CPU。此时低优先级线程无法与高优先级线程争夺 CPU 时间,从而导致任务迟迟完不成、无法释放 lock
#import <libkern/OSAtomic.h>
OSSpinLock lock = OS_SPINLOCK_INIT;
OSSpinLockLock(&lock);
//临界区代码
OSSpinLockUnlock(&lock);
- os_unfair_lock(OSSpinLock的替代方案,iOS10.0以后可用)
#import <os/lock.h>
os_unfair_lock_t unfairLock;
unfairLock = &(OS_UNFAIR_LOCK_INIT);
os_unfair_lock_lock(unfairLock);
//临界区代码
os_unfair_lock_unlock(unfairLock);
信号量
dispatch_semaphore_create(long value); // 创建信号量
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); // 等待信号量
//临界区的代码
dispatch_semaphore_signal(dispatch_semaphore_t deem); // 发送信号量
使用barrier
dispatch_queue_t queue = dispatch_queue_create("queue.concurrent", DISPATCH_QUEUE_CONCURRENT);
__block int value = 1;
dispatch_async(queue, ^{
NSLog(@"task1,value = %d",value);
});
dispatch_async(queue, ^{
NSLog(@"task2, value = %d",value);
});
dispatch_barrier_async(queue, ^{
value = 2;
NSLog(@"barrier, modify value to %d", value);
});
dispatch_async(queue, ^{
NSLog(@"task3, value = %d",value);
});
网友评论