各种锁的效率图
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 准备上锁 当前线程 ");
OSSpinLockLock(&oslosk);
sleep(4);
NSLog(@"线程1");
OSSpinLockUnlock(&oslosk);
NSLog(@"线程1 解锁成功");
NSLog(@"-----------------------------");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"线程2 准备上锁");
OSSpinLockLock(&oslosk);
NSLog(@"线程2");
OSSpinLockUnlock(&oslosk);
NSLog(@"线程2 解锁成功");
});
}
*/
/*
控制台:
function:__OSSpinLockh_hsk_block_invoke line:26 content:线程1 准备上锁 当前线程 🙃Multi Threaded
function:__OSSpinLockh_hsk_block_invoke.16 line:39 content:线程2 准备上锁 🙃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,时间到后会执行其后的语句
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 发送信号");
});
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 发送信号");
});
/*
传入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 发送信号
2017-04-02 09:02:26.194 LockKata1[1336:38096] 线程2
2017-04-02 09:02:26.195 LockKata1[1336:38096] 线程2 发送信号
某一次:
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 发送信号
2017-04-02 09:03:11.100 LockKata1[1353:38735] 线程2
2017-04-02 09:03:11.101 LockKata1[1353:38735] 线程2 发送信号
传入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 发送信号
2017-04-02 09:06:56.946 LockKata1[1376:41653] 线程1 发送信号
*/
}
#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), ^{
//子线程网络请求
NSLog(@"线程1 准备上锁");
pthread_mutex_lock(&pLock);
sleep(3);
NSLog(@"线程1");
pthread_mutex_unlock(&pLock);
});
//线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//子线程网络请求
NSLog(@"线程2 准备上锁");
pthread_mutex_lock(&pLock);
NSLog(@"线程2");
pthread_mutex_unlock(&pLock);
});
/*
lock 和unlock 成对出现
*/
/*
控制台日志:
2017-04-02 09:33:21.575 LockKata1[1493:57547] 线程2 准备上锁
2017-04-02 09:33:21.575 LockKata1[1493:57545] 线程1 准备上锁
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并且给它赋予默认值
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);//设置锁类型,这里设置为递归锁
pthread_mutex_init(&pLock, &attr);
pthread_mutexattr_destroy(&attr);//销毁一个属性对象,在重新进行初始化之前改结构不能重新使用
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) 初始化会出现死锁的情况,递归锁能很好的避免这种情况的死锁;
*/
/*
控制台日志:
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--经典错误例子
//我在这里写的C方法 在AppDelegate.m方法中一样能调用,(*@ο@*) 哇~,夸类了,还是 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是递归调用的。所以每次进入这个block时,都会去加一次锁,而从第二次开始,由于锁已经被使用了且没有解锁,所以它需要等待锁被解除,这样就导致了死锁,线程被阻塞住了。
控制台日志:
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对象时,给了他的标示为0
执行tryLockWhenCondition:时,我们传入的条件标示也是0,所以线程1加锁成功
执行 unlockWithCondition:时,这时候会把condition由0 修改为1
因为condition修改为了1,会先走到线程3,然后线程3又将condition修改为3,最后走了线程2的流程
从上面的结果我们可以发现,NSConditionLock还可以实现任务之间的依赖。
控制台日志:
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
网友评论