==1.@synchronize==
- 用于單例創(chuàng)建,使多線程下保證唯一對象
- 代碼塊可用于數(shù)組中唯一線程讀寫
==2.atomic==
- 是對象的屬性關(guān)鍵字,負(fù)責(zé)對象的原子性操作,不負(fù)責(zé)對象的使用
- atomic 系統(tǒng)會在生成的setter/getter方法里添加鎖,但是這個鎖僅僅是保證了setter/getter存取的安全,并不能保證數(shù)據(jù)結(jié)果正確
- A、B、C等多個線程都要操作同一個對象setter,D線程要getter這個對象的值,那么每個線程都成保證各自數(shù)據(jù)的完整性,但是D線程最后get到的值并不能確定。
==3.OSSpinlock==
自旋鎖
循環(huán)等待訪問,不釋放當(dāng)前資源,類似while(1),負(fù)責(zé)輕量級的+1,-1,如在引用計數(shù)的+1,-1操作
==4.NSRecursiveLock==
遞歸鎖
為了解決NSLock在已加鎖的情況下重復(fù)加鎖,調(diào)用NSRecursiveLock的lock方法,可以使加鎖之后仍然獲取到鎖,并且加鎖。加鎖解鎖成對出現(xiàn)。解決多線程下遞歸方法的加鎖。
==4.NSLock==
線程鎖,為了解決線程同步問題
==5.dispatch_semaphore_t==
信號量,實現(xiàn)對線程同步,資源共享訪問的信號量級鎖
1.GCD信號量簡介
//和GCD的group等用法一致,這個函數(shù)是創(chuàng)建一個dispatch_s`emaphore_類型的信號量
//并且創(chuàng)建的時候需要指定信號量的大小。
dispatch_semaphore_create(long value); // 創(chuàng)建信號量
//發(fā)送信號量。該函數(shù)會對信號量的值進(jìn)行加1操作。
dispatch_semaphore_signal(dispatch_semaphore_t deem); // 發(fā)送信號量
//等待信號量。如果信號量值為0,那么該函數(shù)就會一直等待,也就是不返回(相當(dāng)于阻塞當(dāng)前線程)
//直到該函數(shù)等待的信號量的值大于等于1,該函數(shù)會對信號量的值進(jìn)行減1操作,然后返回。
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); // 等待信號量
2.用信號量機(jī)制使異步線程完成同步操作
兩個任務(wù)雖然是異步的,但仍需要同步執(zhí)行
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
dispatch_group_t grp = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create("concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(grp, queue, ^{
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
NSLog(@"task1 begin : %@",[NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"task1 finish : %@",[NSThread currentThread]);
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
//先等待task1內(nèi)的信號量 直到 task1 finish
});
dispatch_group_async(grp, queue, ^{
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
NSLog(@"task2 begin : %@",[NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"task2 finish : %@",[NSThread currentThread]);
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
});
dispatch_group_notify(grp, dispatch_get_main_queue(), ^{
NSLog(@"refresh UI");
});
}
3 阻塞請求線程
dispatch_async(queue, 0), ^{
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[網(wǎng)絡(luò)請求:^{
//請求回調(diào)
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
});
//多個請求順序執(zhí)行
==6.dispatch_barrier_async和dispatch_barrier_sync==
柵欄方法,用GCD方式實現(xiàn)多讀單寫
dispatch_barrier_sync
需要等待柵欄執(zhí)行完才會執(zhí)行柵欄后面的任務(wù)
dispatch_barrier_async
無需等待柵欄執(zhí)行完,會繼續(xù)往下走(保留在隊列里)
dispatch_async(queue, ^{
NSLog(@"----1-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----2-----%@", [NSThread currentThread]);
});
dispatch_barrier_async(queue, ^{
//會等待內(nèi)部執(zhí)行完才往下走
NSLog(@"----barrier-----%@", [NSThread currentThread]);
});
dispatch_barrier_sync(queue, ^{
//會等待內(nèi)部執(zhí)行完才往下走
NSLog(@"----barrier-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----3-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----4-----%@", [NSThread currentThread]);
});
線程安全的數(shù)組
- 對元素的獲取增加dispatch_sync
如
- (id)objectAtIndex:(NSUInteger)index {
__block id item = nil;
dispatch_sync(self.readWriteQuene, ^{
if (index <= self.array.count - 1) {
item = [self.array objectAtIndex:index];
}
});
return item;
}
- (nullable id)getFirstObject {
__block id item = nil;
dispatch_sync(self.readWriteQuene, ^{
if (self.array.count > 0) {
item = [self.array objectAtIndex:0];
}
});
return item;
}
- (nullable id)getLastObject {
__block id item = nil;
dispatch_sync(self.readWriteQuene, ^{
NSUInteger size = self.array.count;
if (size > 0) {
item = self.array[size - 1];
}
});
return item;
}
- 對數(shù)組操作增加?xùn)艡诜椒?/li>
//synchronized 效率最低
- (void)addObject:(id)anObject {
dispatch_barrier_async(self.readWriteQuene, ^{
[self.array addObject:anObject];
});
}
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index {
dispatch_barrier_async(self.readWriteQuene, ^{
[self.array insertObject:anObject atIndex:index];
});
}
//還有很多操作數(shù)組的方法如removeLastObject