标签:null obj ali str 使用 初始 cond color sel
iOS 中实现线程安全
实现线程安全可以通过加锁、单线程访问等方式。
iOS 中常用的几种锁:
os_unfair_lock
pthread_mutex
dispatch_semaphore
NSLock
NSRecursiveLock
NSCondition
NSConditionLock
@synchorized
单线程访问:
dispatch_queue(DISPATCH_QUEUE_SERIAL),串行队列
dispatch_barrier_async
一、os_unfair_lock
#import <os/lock.h>
static os_unfair_lock _unfailLock; static int _osCount; - (void)unfailrLock { _unfailLock = OS_UNFAIR_LOCK_INIT; // 初始化锁 _osCount = 20; for (int i = 0; i < 20; i++) { dispatch_async(dispatch_get_global_queue(0, 0), ^{ [self unfailrLockBlock]; }); } } - (void)unfailrLockBlock { os_unfair_lock_lock(&_unfailLock); // 加锁 sleep(1); _osCount--; NSLog(@"os_unfair_lock %ld", (long)_osCount); os_unfair_lock_unlock(&_unfailLock); // 解锁 }
二、pthread_mutex
static pthread_mutex_t _mutexLock;
static int _mutexCount;
- (void)pthreadMutex {
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT); // PTHREAD_MUTEX_RECURSIVE 递归锁
pthread_mutex_init(&_mutexLock, &attr); // pthread_mutex_init(&_mutexLock, NULL);
_mutexCount = 20;
for (int i = 0; i < 20; i++) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self pthreadMutexBlock];
});
}
}
- (void)pthreadMutexBlock {
pthread_mutex_lock(&_mutexLock);
sleep(1);
_mutexCount--;
NSLog(@"pthread_mutex %ld", (long)_mutexCount);
pthread_mutex_unlock(&_mutexLock);
}
三、dispatch_semaphore,当信号量小于1的时候,线程进入休眠等待。
static dispatch_semaphore_t _semaphore;
static int _semaphoreCount;
- (void)semaphore {
_semaphore = dispatch_semaphore_create(1);
_semaphoreCount = 20;
for (int i = 0; i < 20; i++) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self semaphoreBlock];
});
}
}
- (void)semaphoreBlock {
dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);
sleep(1);
_semaphoreCount--;
NSLog(@"semaphore %ld", (long)_semaphoreCount);
dispatch_semaphore_signal(_semaphore);
}
四、NSLock 对pthread_mutex 普通类型锁的封装,NSRecursiveLock pthread_mutex 递归类型锁的封装。递归锁,同一个线程可以对一个锁多次加锁。
static NSLock *_nslock;
static int _lockCount;
- (void)nslock {
_nslock = [[NSLock alloc] init];
_lockCount = 20;
for (int i = 0; i < 20; i++) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self nslockBlock];
});
}
}
- (void)nslockBlock {
[_nslock lock];
sleep(1);
_lockCount--;
NSLog(@"nslock %ld", (long)_lockCount);
[_nslock unlock];
}
五、NSCondition、NSConditionLock 是对 pthread_mutex 的 condition 属性封装。
static NSCondition *_cond;
static int _condCount;
- (void)condition {
_cond = [[NSCondition alloc] init];
_condCount = 10;
for (int i = 0; i < 15; i++) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self reduce];
});
}
for (int i = 0; i < 10; i++) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self add];
});
}
}
- (void)reduce {
[_cond lock];
if (_condCount == 0) {
[_cond wait];
}
sleep(1);
_condCount--;
NSLog(@"reduce %ld", (long)_condCount);
[_cond unlock];
}
- (void)add {
[_cond lock];
if (_condCount >= 0) {
[_cond signal]; // 一次singnal只能唤醒一个在等待condition的线程,如果想唤醒多个可使用[_cond broadcast];
}
sleep(1);
_condCount++;
NSLog(@"add %ld", (long)_condCount);
[_cond unlock];
}
六、@synchorized,runtime 会给 synchorized 调用的每一个对象分配一个递归锁并存储在哈希表中,因此效率比较低不建议使用。
@synchorized(nil) 会加锁失败。
七、pthread_rwlock 用于文件读写操作的锁,pthread_rwlock_rdlock(&lock) 读操作加锁,临界区(被加锁的代码)并发执行,pthread_rwlock_wrlock(&lock))写操作加锁,临界区只会串行执行
static pthread_rwlock_t _rwlock = PTHREAD_RWLOCK_INITIALIZER;
static int _rwlockCount;
- (void)pthreadRWLock {
_rwlockCount = 10;
for (int i = 0; i < 15; i++) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self rwRead];
});
}
for (int i = 0; i < 2; i++) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self rwWrite];
});
}
}
- (void)rwRead {
pthread_rwlock_rdlock(&_rwlock);
sleep(1);
NSLog(@"pthread_rw read %ld", (long)_rwlockCount);
pthread_rwlock_unlock(&_rwlock);
}
- (void)rwWrite {
pthread_rwlock_wrlock(&_rwlock);
sleep(1);
_rwlockCount++;
NSLog(@"pthread_rw write %ld", (long)_rwlockCount);
pthread_rwlock_unlock(&_rwlock);
}
输出
2020-06-08 22:46:01.137977+0800 多线程[7019:829191] pthread_rw read 10
2020-06-08 22:46:01.137977+0800 多线程[7019:829189] pthread_rw read 10
2020-06-08 22:46:01.137978+0800 多线程[7019:829194] pthread_rw read 10
2020-06-08 22:46:01.137978+0800 多线程[7019:829190] pthread_rw read 10
2020-06-08 22:46:01.137989+0800 多线程[7019:829195] pthread_rw read 10
2020-06-08 22:46:01.137977+0800 多线程[7019:829188] pthread_rw read 10
2020-06-08 22:46:01.138022+0800 多线程[7019:829256] pthread_rw read 10
2020-06-08 22:46:01.138021+0800 多线程[7019:829252] pthread_rw read 10
2020-06-08 22:46:01.138022+0800 多线程[7019:829257] pthread_rw read 10
2020-06-08 22:46:01.138024+0800 多线程[7019:829255] pthread_rw read 10
2020-06-08 22:46:01.138022+0800 多线程[7019:829254] pthread_rw read 10
2020-06-08 22:46:01.138028+0800 多线程[7019:829253] pthread_rw read 10
2020-06-08 22:46:01.138047+0800 多线程[7019:829258] pthread_rw read 10
2020-06-08 22:46:01.138048+0800 多线程[7019:829259] pthread_rw read 10
2020-06-08 22:46:01.138053+0800 多线程[7019:829260] pthread_rw read 10
2020-06-08 22:46:02.143706+0800 多线程[7019:829261] pthread_rw write 11
2020-06-08 22:46:03.144493+0800 多线程[7019:829262] pthread_rw write 12
七、atomic、自旋锁与互斥锁
atomic:原子性,当一个属性被标记为atomic的时候,get和set方法通过加锁的方法实现原子性,iOS手机上一般不使用atomic属性。
自旋锁:当线程获取不到锁的时候,线程处于忙等状态(类似while循环),cpu处于忙等状态。
互斥锁:当线程获取不到锁的时候,线程进入休眠状态,cpu 资源得到释放。目前 iOS 的锁基本都是互斥锁。
标签:null obj ali str 使用 初始 cond color sel
原文地址:https://www.cnblogs.com/beautylcy/p/13069170.html