推薦系統直接學習小碼哥iOS底層原理班---MJ老師的課確實不錯,強推一波。ios
並行:多個任務併發(同時)執行 串行:一個任務執行完畢後,再執行下一個任務數組
同步:在當前線程中執行任務,不具有開啓新線程的能力 異步:在新的線程中執行任務,具有開啓新線程的能力安全
會開闢新線程的兩種狀況bash
其他狀況、所有將會置於當前線程/主線程(主隊列任務)下執行。多線程
1塊資源可能會被多個線程共享,也就是
多個線程可能會訪問同一塊資源
併發
讀寫
進行枷鎖操做
等待鎖的線程會處於忙等(busy-wait)狀態,一直佔用着CPU資源異步
#import <libkern/OSAtomic.h>
@interface OSSpinLockDemo()
@property (assign, nonatomic) OSSpinLock lock;
@end
@implementation OSSpinLockDemo
- (instancetype)init
{
if (self = [super init]) {
self.lock = OS_SPINLOCK_INIT;
}
return self;
}
- (void)test
{
OSSpinLockLock(&_lock);
//同步操做
OSSpinLockUnlock(&_lock);
}
@end
複製代碼
OSSpinLock目前已經再也不安全,可能會出現優先級反轉問題async
若是等待鎖的線程優先級較高,它會一直佔用着CPU資源,優先級低的線程就有可能得不到資源致使沒法釋放鎖。性能
等待os_unfair_lock鎖的線程會處於休眠狀態,並不是忙等學習
os_unfair_lock用於取代不安全的OSSpinLock ,從iOS10開始才支持
<os/lock.h>
@interface OSUnfairLockDemo()
@property (assign, nonatomic) os_unfair_lock lock;
@end
@implementation OSUnfairLockDemo
- (instancetype)init
{
if (self = [super init]) {
self.lock = OS_UNFAIR_LOCK_INIT;
}
return self;
}
- (void)__saleTicket
{
os_unfair_lock_lock(&_lock);
//耗時操做
os_unfair_lock_unlock(&_lock);
}
@end
複製代碼
PTHREAD_MUTEX_DEFAULT或PTHREAD_MUTEX_NORMAL下的 pthread_mutex 會產生互斥效果
NSLock是對mutex普通鎖的封裝
容許同一個線程對一把鎖進行重複加鎖
PTHREAD_MUTEX_RECURSIVE 下的 pthread_mutex 會產生遞歸效果
![]()
NSRecursiveLock也是對mutex遞歸鎖的封裝,API跟NSLock基本一致
@synchronized是對mutex遞歸鎖的封裝
@synchronized(obj)內部會生成obj對應的遞歸鎖並存在hash表中,而後進行加鎖、解鎖操做。性能最差
-(void)test {
@synchronized(self) {
NSLog(@"2");
[self tess];
sleep(5);
}
}
複製代碼
可讓一個線程在加鎖途中等待另外一個線程完成某個動做後繼續加鎖執行
相似消費者在商場等着商家調貨,而後繼續購買。
在上鎖狀態下能夠暫時將鎖放開,休眠並等待某個條件
當其餘線程對條件發送信號,喚醒繼續加鎖並執行
@interface MutexDemo3()
@property (assign, nonatomic) pthread_mutex_t mutex;
@property (assign, nonatomic) pthread_cond_t cond;
@property (strong, nonatomic) NSMutableArray *data;
@end
@implementation MutexDemo3
- (instancetype)init
{
if (self = [super init]) {
// 初始化屬性
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
// 初始化鎖
pthread_mutex_init(&_mutex, &attr);
// 銷燬屬性
pthread_mutexattr_destroy(&attr);
// 初始化條件
pthread_cond_init(&_cond, NULL);
self.data = [NSMutableArray array];
}
return self;
}
- (void)otherTest
{
[[[NSThread alloc] initWithTarget:self selector:@selector(__remove) object:nil] start];
[[[NSThread alloc] initWithTarget:self selector:@selector(__add) object:nil] start];
}
// 線程1
// 刪除數組中的元素
- (void)__remove
{
pthread_mutex_lock(&_mutex);
NSLog(@"__remove - begin");
if (self.data.count == 0) {
// 等待喚醒
pthread_cond_wait(&_cond, &_mutex);
}
[self.data removeLastObject];
NSLog(@"刪除了元素");
pthread_mutex_unlock(&_mutex);
}
// 線程2
// 往數組中添加元素
- (void)__add
{
pthread_mutex_lock(&_mutex);
sleep(1);
[self.data addObject:@"Test"];
NSLog(@"添加了元素");
// 發送喚醒信號
pthread_cond_signal(&_cond);
pthread_mutex_unlock(&_mutex);
}
- (void)dealloc
{
pthread_mutex_destroy(&_mutex);
pthread_cond_destroy(&_cond);
}
@end
複製代碼
NSCondition是對mutex和cond的封裝
NSConditionLock是對NSCondition的進一步封裝,能夠設置具體的條件值
- (instancetype)init
{
if (self = [super init]) {
self.conditionLock = [[NSConditionLock alloc] initWithCondition:1];
}
return self;
}
- (void)otherTest
{
[[[NSThread alloc] initWithTarget:self selector:@selector(__one) object:nil] start];
[[[NSThread alloc] initWithTarget:self selector:@selector(__two) object:nil] start];
[[[NSThread alloc] initWithTarget:self selector:@selector(__three) object:nil] start];
}
- (void)__one
{
[self.conditionLock lock];
NSLog(@"__one");
sleep(1);
[self.conditionLock unlockWithCondition:2];
}
- (void)__two
{
[self.conditionLock lockWhenCondition:2];
NSLog(@"__two");
sleep(1);
[self.conditionLock unlockWithCondition:3];
}
複製代碼
信號量的初始值爲1,表明同時只容許1條線程訪問資源,保證線程同步
也能夠控制線程的最大併發數
- (void)test
{
// 若是信號量的值 > 0,就讓信號量的值減1,而後繼續往下執行代碼
// 若是信號量的值 <= 0,就會休眠等待,直到信號量的值變成>0,就讓信號量的值減1,而後繼續往下執行代碼
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
sleep(2);
NSLog(@"test - %@", [NSThread currentThread]);
// 讓信號量的值+1
dispatch_semaphore_signal(self.semaphore);
}
複製代碼
atomic用於保證屬性setter、getter的原子性操做,至關於在getter和setter內部加了線程同步的鎖
能夠參考源碼objc4的objc-accessors
讀寫鎖
@interface ViewController ()
@property (strong, nonatomic) dispatch_queue_t queue;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// queue.maxConcurrentOperationCount = 5;
// dispatch_semaphore_create(5);
self.queue = dispatch_queue_create("rw_queue", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 10; i++) {
dispatch_async(self.queue, ^{
[self read];
});
dispatch_async(self.queue, ^{
[self read];
});
dispatch_async(self.queue, ^{
[self read];
});
dispatch_barrier_async(self.queue, ^{
[self write];
});
}
}
- (void)read {
sleep(1);
NSLog(@"read");
}
- (void)write
{
sleep(1);
NSLog(@"write");
}
@end
複製代碼
@interface ViewController ()
@property (assign, nonatomic) pthread_rwlock_t lock;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 初始化鎖
pthread_rwlock_init(&_lock, NULL);
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
for (int i = 0; i < 10; i++) {
dispatch_async(queue, ^{
[self read];
});
dispatch_async(queue, ^{
[self write];
});
}
}
- (void)read {
pthread_rwlock_rdlock(&_lock);
sleep(1);
NSLog(@"%s", __func__);
pthread_rwlock_unlock(&_lock);
}
- (void)write
{
pthread_rwlock_wrlock(&_lock);
sleep(1);
NSLog(@"%s", __func__);
pthread_rwlock_unlock(&_lock);
}
- (void)dealloc
{
pthread_rwlock_destroy(&_lock);
}
@end
複製代碼