各種鎖的效率圖
iOS鎖的效率.png
//
// ViewController.m
// LockKata1
//
// Created by Code_Hou on 2017/4/2.
// Copyright ? 2017年 侯森魁. All rights reserved.
//
#import "ViewController.h"
#import <libkern/OSAtomic.h>
#import <pthread.h>
@interface ViewController ()
@end
@implementation ViewController
#pragma mark--自旋鎖
/*
void OSSpinLockh_hsk(){
__block OSSpinLock oslosk =OS_SPINLOCK_INIT;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"線程1 準(zhǔn)備上鎖 當(dāng)前線程 ");
OSSpinLockLock(&oslosk);
sleep(4);
NSLog(@"線程1");
OSSpinLockUnlock(&oslosk);
NSLog(@"線程1 解鎖成功");
NSLog(@"-----------------------------");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"線程2 準(zhǔn)備上鎖");
OSSpinLockLock(&oslosk);
NSLog(@"線程2");
OSSpinLockUnlock(&oslosk);
NSLog(@"線程2 解鎖成功");
});
}
*/
/*
控制臺:
function:__OSSpinLockh_hsk_block_invoke line:26 content:線程1 準(zhǔn)備上鎖 當(dāng)前線程 ??Multi Threaded
function:__OSSpinLockh_hsk_block_invoke.16 line:39 content:線程2 準(zhǔn)備上鎖 ??Multi Threaded
function:__OSSpinLockh_hsk_block_invoke line:30 content:線程1 ??Multi Threaded
function:__OSSpinLockh_hsk_block_invoke line:32 content:線程1 解鎖成功 ??Multi Threaded
function:__OSSpinLockh_hsk_block_invoke line:33 content:----------------------------- ??Multi Threaded
function:__OSSpinLockh_hsk_block_invoke.16 line:41 content:線程2 ??Multi Threaded
function:__OSSpinLockh_hsk_block_invoke.16 line:43 content:線程2 解鎖成功 ??Multi Threaded
*/
#pragma mark----信號量
void dispatch_semaphore(){
dispatch_semaphore_t signal =dispatch_semaphore_create(0);//傳入值必須>=0,若傳入為0則阻塞線程并等待tiomout,時間到后會執(zhí)行其后的語句
dispatch_time_t overTime =dispatch_time(DISPATCH_TIME_NOW, 3.0f*NSEC_PER_SEC);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"線程1 等待ing");
dispatch_semaphore_wait(signal, overTime);//signal 值 -1
NSLog(@"線程1");
dispatch_semaphore_signal(signal);//signal 值+1
NSLog(@"線程1 發(fā)送信號");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"線程2 等待ing");
dispatch_semaphore_wait(signal, overTime);
NSLog(@"線程2");
dispatch_semaphore_signal(signal);
NSLog(@"線程2 發(fā)送信號");
});
/*
傳入1 overTime 不會生效
dispatch_semaphore_t signal =dispatch_semaphore_create(1);
控制臺:
某一次:
2017-04-02 09:02:26.193 LockKata1[1336:38092] 線程1 等待ing
2017-04-02 09:02:26.194 LockKata1[1336:38092] 線程1
2017-04-02 09:02:26.193 LockKata1[1336:38096] 線程2 等待ing
2017-04-02 09:02:26.194 LockKata1[1336:38092] 線程1 發(fā)送信號
2017-04-02 09:02:26.194 LockKata1[1336:38096] 線程2
2017-04-02 09:02:26.195 LockKata1[1336:38096] 線程2 發(fā)送信號
某一次:
2017-04-02 09:03:11.098 LockKata1[1353:38732] 線程1 等待ing
2017-04-02 09:03:11.098 LockKata1[1353:38735] 線程2 等待ing
2017-04-02 09:03:11.098 LockKata1[1353:38732] 線程1
2017-04-02 09:03:11.100 LockKata1[1353:38732] 線程1 發(fā)送信號
2017-04-02 09:03:11.100 LockKata1[1353:38735] 線程2
2017-04-02 09:03:11.101 LockKata1[1353:38735] 線程2 發(fā)送信號
傳入0 overTime 生效
dispatch_semaphore_t signal =dispatch_semaphore_create(0)
控制臺:
2017-04-02 09:06:53.872 LockKata1[1376:41653] 線程1 等待ing
2017-04-02 09:06:53.872 LockKata1[1376:41638] 線程2 等待ing
2017-04-02 09:06:56.946 LockKata1[1376:41653] 線程1
2017-04-02 09:06:56.946 LockKata1[1376:41638] 線程2
2017-04-02 09:06:56.946 LockKata1[1376:41638] 線程2 發(fā)送信號
2017-04-02 09:06:56.946 LockKata1[1376:41653] 線程1 發(fā)送信號
*/
}
#pragma mark--互斥鎖
void pthread_mutex_hsk(){
pthread_mutex_t pLock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
// pthread_mutex_t_init(&pLock,NULL);
//線程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//子線程網(wǎng)絡(luò)請求
NSLog(@"線程1 準(zhǔn)備上鎖");
pthread_mutex_lock(&pLock);
sleep(3);
NSLog(@"線程1");
pthread_mutex_unlock(&pLock);
});
//線程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//子線程網(wǎng)絡(luò)請求
NSLog(@"線程2 準(zhǔn)備上鎖");
pthread_mutex_lock(&pLock);
NSLog(@"線程2");
pthread_mutex_unlock(&pLock);
});
/*
lock 和unlock 成對出現(xiàn)
*/
/*
控制臺日志:
2017-04-02 09:33:21.575 LockKata1[1493:57547] 線程2 準(zhǔn)備上鎖
2017-04-02 09:33:21.575 LockKata1[1493:57545] 線程1 準(zhǔn)備上鎖
2017-04-02 09:33:21.576 LockKata1[1493:57547] 線程2
2017-04-02 09:33:24.646 LockKata1[1493:57545] 線程1
*/
}
#pragma mark---遞歸鎖
void pthread_mutex_recursive(){
static pthread_mutex_t pLock;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);//初始化attr并且給它賦予默認(rèn)值
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);//設(shè)置鎖類型虱岂,這里設(shè)置為遞歸鎖
pthread_mutex_init(&pLock, &attr);
pthread_mutexattr_destroy(&attr);//銷毀一個屬性對象,在重新進(jìn)行初始化之前改結(jié)構(gòu)不能重新使用
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
static void (^RecursiveBlock)(int);
RecursiveBlock = ^(int value){
pthread_mutex_lock(&pLock);
if (value > 0) {
NSLog(@"value:%d",value);
RecursiveBlock(value-1);
}
pthread_mutex_unlock(&pLock);
};
RecursiveBlock(5);
});
/*
上面的代碼如果我們用 pthread_mutex_init(&pLock, NULL) 初始化會出現(xiàn)死鎖的情況菠红,遞歸鎖能很好的避免這種情況的死鎖第岖;
*/
/*
控制臺日志:
2017-04-02 09:58:24.701 LockKata1[1591:70699] value:5
2017-04-02 09:58:24.701 LockKata1[1591:70699] value:4
2017-04-02 09:58:24.703 LockKata1[1591:70699] value:3
2017-04-02 09:58:24.704 LockKata1[1591:70699] value:2
2017-04-02 09:58:24.705 LockKata1[1591:70699] value:1
*/
}
#pragma mark---NSLock
void NSLock_hsk(){
NSLock *lock = [NSLock new];
//線程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"線程1 嘗試加鎖ing...");
[lock lock];
sleep(3);//睡眠3秒
NSLog(@"線程1");
[lock unlock];
NSLog(@"線程1解鎖成功");
});
//線程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"線程2 嘗試加鎖ing...");
BOOL x = [lock lockBeforeDate:[NSDate dateWithTimeIntervalSinceNow:6]];
if (x) {
NSLog(@"線程2");
[lock unlock];
}else{
NSLog(@"失敗");
}
});
/*
2017-04-02 10:10:25.265 LockKata1[1663:78655] 線程1 嘗試加鎖ing...
2017-04-02 10:10:25.265 LockKata1[1663:78654] 線程2 嘗試加鎖ing...
2017-04-02 10:10:28.334 LockKata1[1663:78655] 線程1
2017-04-02 10:10:28.334 LockKata1[1663:78654] 線程2
2017-04-02 10:10:28.334 LockKata1[1663:78655] 線程1解鎖成功
*/
}
#pragma mark---NSCondition
void NSCondition_hsk(){
NSCondition *cLock = [NSCondition new];
//線程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"start");
[cLock lock];
[cLock waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];
//等待2 秒
NSLog(@"線程1");
[cLock unlock];
});
/*
*/
/*
2017-04-02 10:16:21.217 LockKata1[1709:82528] start
2017-04-02 10:16:23.287 LockKata1[1709:82528] 線程1
*/
}
void NSCondition_hsk1(){
NSCondition *cLock =[NSCondition new];
//線程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[cLock lock];
NSLog(@"線程1加鎖成功");
[cLock wait];
NSLog(@"線程1");
[cLock unlock];
});
//線程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[cLock lock];
NSLog(@"線程2加鎖成功");
[cLock wait];
NSLog(@"線程2");
[cLock unlock];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(2);
NSLog(@"喚醒一個等待的線程");
[cLock broadcast];
});
/*
[cLock signal]
控制臺日志:
2017-04-02 10:26:38.063 LockKata1[1751:87871] 線程1加鎖成功
2017-04-02 10:26:38.064 LockKata1[1751:87872] 線程2加鎖成功
2017-04-02 10:26:40.134 LockKata1[1751:87874] 喚醒一個等待的線程
2017-04-02 10:26:40.135 LockKata1[1751:87871] 線程1
[cLock broadcast];
控制臺日志:
2017-04-02 10:36:34.442 LockKata1[1782:91902] 線程1加鎖成功
2017-04-02 10:36:34.443 LockKata1[1782:91900] 線程2加鎖成功
2017-04-02 10:36:36.504 LockKata1[1782:91899] 喚醒一個等待的線程
2017-04-02 10:36:36.505 LockKata1[1782:91902] 線程1
2017-04-02 10:36:36.506 LockKata1[1782:91900] 線程2
*/
}
#pragma mark--經(jīng)典錯誤例子
//我在這里寫的C方法 在AppDelegate.m方法中一樣能調(diào)用,(*@ο@*) 哇~试溯,夸類了蔑滓,還是 C語言好
void errorUseWithNSLock(){
NSLock *rLock = [NSLock new];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
static void(^RecursiveBlock)(int);
RecursiveBlock = ^(int value){
[rLock lock];
if (value>0) {
NSLog(@"線程%d",value);
RecursiveBlock(value - 1);
}
[rLock unlock];
};
RecursiveBlock(4);
});
/*
這是一段典型的死鎖情況。在我們的線程中,RecursiveMethod是遞歸調(diào)用的键袱。所以每次進(jìn)入這個block時燎窘,都會去加一次鎖,而從第二次開始蹄咖,由于鎖已經(jīng)被使用了且沒有解鎖褐健,所以它需要等待鎖被解除,這樣就導(dǎo)致了死鎖澜汤,線程被阻塞住了蚜迅。
控制臺日志:
2017-04-02 10:47:37.882 LockKata1[1823:97654] 線程4
2017-04-02 10:47:37.883 LockKata1[1823:97654] *** -[NSLock lock]: deadlock (<NSLock: 0x7b858f80> '(null)')
2017-04-02 10:47:37.884 LockKata1[1823:97654] *** Break on _NSLockError() to debug.
*/
}
void NSRecursiveLock_hsk(){
NSRecursiveLock *rLock =[NSRecursiveLock new];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
static void(^RecursiveBlock)(int);
RecursiveBlock = ^(int value){
[rLock lock];
if (value>0) {
NSLog(@"線程%d",value);
RecursiveBlock(value-1);
}
[rLock unlock];
};
RecursiveBlock(5);
});
/*
控制臺:
2017-04-02 10:55:48.718 LockKata1[1855:100893] 線程5
2017-04-02 10:55:48.718 LockKata1[1855:100893] 線程4
2017-04-02 10:55:48.719 LockKata1[1855:100893] 線程3
2017-04-02 10:55:48.721 LockKata1[1855:100893] 線程2
2017-04-02 10:55:48.725 LockKata1[1855:100893] 線程1
*/
}
#pragma mark----@synchronized 條件鎖
- (void) synchronized_hsk{
//線程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized (self) {
sleep(2);
NSLog(@"線程1");
}
});
//線程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized (self) {
NSLog(@"線程2");
}
});
/*
2017-04-02 11:03:11.972 LockKata1[1885:104889] 線程2
2017-04-02 11:03:14.013 LockKata1[1885:104890] 線程1
*/
}
void NSConditonLock_hsk(){
NSConditionLock *cLock =[[NSConditionLock alloc]initWithCondition:0];
//線程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if ([cLock tryLockWhenCondition:0]) {
NSLog(@"線程1");
[cLock unlockWithCondition:1];
}else{
NSLog(@"失敗");
}
});
//線程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[cLock lockWhenCondition:3];
NSLog(@"線程2");
[cLock unlockWithCondition:2];
});
//線程3
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[cLock lockWhenCondition:1];
NSLog(@"線程3");
[cLock unlockWithCondition:3];
});
/*
我們在初始化NSConditionLock對象時,給了他的標(biāo)示為0
執(zhí)行tryLockWhenCondition:時银亲,我們傳入的條件標(biāo)示也是0慢叨,所以線程1加鎖成功
執(zhí)行 unlockWithCondition:時纽匙,這時候會把condition由0 修改為1
因?yàn)閏ondition修改為了1务蝠,會先走到線程3,然后線程3又將condition修改為3烛缔,最后走了線程2的流程
從上面的結(jié)果我們可以發(fā)現(xiàn)馏段,NSConditionLock還可以實(shí)現(xiàn)任務(wù)之間的依賴。
控制臺日志:
2017-04-02 11:10:25.099 LockKata1[1914:108665] 線程1
2017-04-02 11:10:25.101 LockKata1[1914:108667] 線程3
2017-04-02 11:10:25.101 LockKata1[1914:108664] 線程2
*/
}
- (void)viewDidLoad {
[super viewDidLoad];
NSConditonLock_hsk();
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end