标签:10 rw iOS dispatch 线程 pthread 2020 多线程
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
<style></style>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 的锁基本都是互斥锁。
<style></style> <style></style>
标签:10,rw,iOS,dispatch,线程,pthread,2020,多线程 来源: https://www.cnblogs.com/beautylcy/p/13069170.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。