1. @synchronized 關鍵字加鎖
2. NSLock 對象鎖
3. NSCondition 條件鎖1
4. NSConditionLock 條件鎖2
5. NSRecursiveLock 遞歸鎖
6. pthread_mutex 互斥鎖(C語言)
7. pthread_mutex(recursive) 互斥鎖(C語言)2-也是遞歸鎖一種類似NSConditionLock
8. dispatch_semaphore 信號量實現(xiàn)加鎖(GCD)
9. OSSpinLock 自旋鎖!H銮病:ぁ1渡荨=厍浮(已不安全)無法保證和控制優(yōu)先級不同的線程的調(diào)度,除非所有優(yōu)先級都是一樣的炸庞,而除非帶出來的話往往木有意義
一.不廢話直接貼代碼
GitHub地址:https://github.com/Yjunjie/MultithreadingAndLock/tree/master
基本都是根據(jù)實際情況設立的情境最欠,買票,網(wǎng)絡數(shù)據(jù)加載處理积担,網(wǎng)絡數(shù)據(jù)上傳處理等等陨晶。部分操作如圖:
1.多售票員賣票情境
http://upload-images.jianshu.io/upload_images/6285199-f054d3f3b9473816.gif?imageMogr2/auto-orient/strip
2.用戶路線緩存,經(jīng)緯度數(shù)據(jù)點上傳
http://upload-images.jianshu.io/upload_images/6285199-4c1eeabbe9ee3f3e.gif?imageMogr2/auto-orient/strip
3.各種鎖性能對比帝璧,都進行一千萬次加鎖空操作先誉。
這里需要做個簡要說明,本來就是毫秒級的操作的烁,在某些情況下受硬件影響褐耳,我分別用真機(5C,6,7P),模擬器都試了下,結果不一變化還蠻多渴庆。但是基本都和理論相差不大铃芦。主要get的結果就是
1.性能最佳:但是OSSpinLock 自旋鎖已經(jīng)不再安全,不推薦或者慎重使用
OSSpinLock 自旋鎖
dispatch_semaphore 信號量實現(xiàn)加鎖(GCD)
2.性能次之:NSLock貌似還比較折中襟雷,使用頻率貌似還蠻高
NSLock 對象鎖
NSCondition 條件鎖
3.耗時最長:正常情況下沒有例外過刃滓,不考怎么慮性能耗時那就@synchronized 關鍵字鎖
@synchronized 關鍵字鎖
各種鎖性能對比實際操作圖示如下:
全部代碼
因為只是測試各類鎖的特性問題,我沒有一一處理耸弄,畢竟對比測試有個所以然就夠了咧虎,所以期間操作有些鎖的測試不能重復測試需要殺死程序重啟測試。
#ifdef DEBUG
# define DEBUGLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
# define DEBUGLog(...)
#endif
#define Screen_Width ([UIScreen mainScreen].bounds.size.width)
#define Screen_Height ([UIScreen mainScreen].bounds.size.height)
#import "ViewController.h"
#import <objc/runtime.h>
#import <pthread.h>
#import <libkern/OSAtomic.h>
@interface ViewController ()
{
NSLock * _lock;
NSComparator sort;
UILabel *lab;
NSMutableString *mutLogStr;
NSArray *nameArray;
}
//剩余票數(shù)
@property(nonatomic,assign) int leftTicketsCount;
@property(nonatomic,assign) int leftTicketsCount0;
@property(nonatomic,strong)NSMutableArray *threadArr;//存放線程數(shù)組
@property(nonatomic,strong)NSMutableArray *methodsArr;//存放方法名數(shù)組
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
// Do any additional setup after loading the view, typically from a nib.
/**
1. @synchronized 關鍵字加鎖
2. NSLock 對象鎖
3. NSCondition 條件鎖1
4. NSConditionLock 條件鎖2
5. NSRecursiveLock 遞歸鎖
6. pthread_mutex 互斥鎖(C語言)
7. pthread_mutex(recursive) 互斥鎖(C語言)2
8. dispatch_semaphore 信號量實現(xiàn)加鎖(GCD)
9. OSSpinLock 自旋鎖P鹱@峡汀!U鸲!k逝椤(已不安全)
**/
/**
數(shù)據(jù)對象初始化
**/
_threadArr = [[NSMutableArray alloc]init];
_methodsArr = [[NSMutableArray alloc]init];
_lock = [[NSLock alloc] init];
mutLogStr = [[NSMutableString alloc]init];
/**
界面UI按鈕初始化
**/
nameArray=[NSArray arrayWithObjects:@"關鍵字鎖-@synchronized",@"對象鎖-NSLock",@"條件鎖-1NSCondition",@"條件鎖2-NSConditionLock",@"遞歸鎖-NSRecursiveLock",@"互斥鎖-pthread_mutex",@"互斥鎖2-pthread_mutex(recursive)",@"信號量實現(xiàn)加鎖-dispatch_semaphore",@"自旋鎖-OSSpinLock自旋鎖",@"一千萬次線程鎖空操作性能對比-runLock", nil];
for (int i=0;i<[nameArray count];i++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.tag = i+1;
[button setTitle:[nameArray objectAtIndex:i] forState:UIControlStateNormal];
[button setFrame:CGRectMake(20,30+35*i,Screen_Width-40, 25)];
[self.view addSubview:button];
[button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
CALayer *layer = [button layer];
layer.borderColor = [UIColor purpleColor].CGColor;
layer.borderWidth = 1;
}
lab = [[UILabel alloc]init];
lab.numberOfLines = 0;
lab.textColor = [UIColor whiteColor];
[lab setFrame:CGRectMake(0,30+(35*[nameArray count]),Screen_Width,Screen_Height-(30+35*[nameArray count]))];
[self.view addSubview:lab];
CALayer *layer = [lab layer];
layer.borderColor = [UIColor whiteColor].CGColor;
layer.borderWidth = 3;
/**
獲取所有鎖方法
**/
unsigned int count;
Method *methods = class_copyMethodList([self class], &count);
for (int i = 0; i < count; i++)
{
Method method = methods[i];
SEL selector = method_getName(method);
NSString *name = NSStringFromSelector(selector);
if ([name hasPrefix:@"sellTickets"]) {
[_methodsArr addObject:name];
}
NSLog(@"方法 名字 ==== %@",name);
NSLog(@"Test '%@' completed successfuly", [name substringFromIndex:4]);
}
/**
字符串數(shù)組排序
**/
NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch|NSNumericSearch|
NSWidthInsensitiveSearch|NSForcedOrderingSearch;
sort = ^(NSString *obj1,NSString *obj2){
NSRange range = NSMakeRange(0,obj1.length);
return [obj1 compare:obj2 options:comparisonOptions range:range];
};
NSArray *resultArray = [_methodsArr sortedArrayUsingComparator:sort];
[_methodsArr setArray:resultArray];
NSLog(@"字符串數(shù)組排序結果%@",resultArray);
self.leftTicketsCount=100;
}
-(void)meathodGet:(SEL)selector
{
if (_threadArr.count>0) {
for (int i=0; i<_threadArr.count; i++) {
NSThread *thread=[_threadArr objectAtIndex:i];
[thread cancel];
thread = nil;
}
}
[_threadArr removeAllObjects];
for (int i=0; i<10; i++) {
NSThread *thread=[[NSThread alloc]initWithTarget:self selector:selector object:nil];
char chStr = i + 'A';
thread.name=[NSString stringWithFormat:@"售票員%c",chStr];
[_threadArr addObject:thread];
[thread start];
}
}
/**
1. @synchronized 關鍵字加鎖
@synchronized指令實現(xiàn)鎖的優(yōu)點就是我們不需要在代碼中顯式的創(chuàng)建鎖對象,便可以實現(xiàn)鎖的機制苇瓣,但作為一種預防措施尉间,
@synchronized塊會隱式的添加一個異常處理例程來保護代碼,該處理例程會在異常拋出的時候自動的釋放互斥鎖。所以如果不想讓隱
式的異常處理例程帶來額外的開銷哲嘲,你可以考慮使用鎖對象贪薪。
**/
-(void)sellTickets
{
while (1) {
@synchronized(self){//只能加一把鎖 ['s??kr?na?zd]
//1.先檢查票數(shù)
int count=self.leftTicketsCount;
if (count>0) {
//休眠一段時間
sleep(1);
//2.票數(shù)-1
self.leftTicketsCount= count-1;
//獲取當前線程
NSThread *current=[NSThread currentThread];
[self logGetStr:[NSString stringWithFormat:@"%@--賣了一張票,還剩余%d張票",current.name,self.leftTicketsCount]];
DEBUGLog(@"%@--賣了一張票眠副,還剩余%d張票",current.name,self.leftTicketsCount);
}else{
//退出線程
[NSThread exit];
}
}
}
}
/**
2. NSLock 對象鎖
NSLock是我們經(jīng)常所使用的画切,除lock和unlock方法外,NSLock還提供了tryLock,lockBeforeDate:兩個方法
tryLock:會嘗試加鎖囱怕,如果鎖不可用(已經(jīng)被鎖住)霍弹,剛并不會阻塞線程,并返回NO娃弓。
lockBeforeDate:方法會在所指定Date之前嘗試加鎖典格,如果在指定時間之前都不能加鎖,則返回NO台丛。
**/
- (void)sellTickets2
{
while (1) {
[_lock lock];
int count=self.leftTicketsCount;
if (count>0) {
//休眠一段時間
sleep(1);
//2.票數(shù)-1
self.leftTicketsCount= count-1;
//獲取當前線程
NSThread *current=[NSThread currentThread];
[self logGetStr:[NSString stringWithFormat:@"%@--賣了一張票耍缴,還剩余%d張票",current.name,self.leftTicketsCount]];
NSLog(@"%@--賣了一張票,還剩余%d張票",current.name,self.leftTicketsCount);
}else{
//退出線程
[NSThread exit];
}
[_lock unlock];
}
}
/**
3 NSCondition 條件鎖1
一種最基本的條件鎖挽霉。手動控制線程wait和signal防嗡。當我們在使用多線程的時候,普通的鎖只是直接的鎖與不鎖侠坎,而我們在處理資源
共享的時候很多情況下下需要滿足一定條件的情況下才能打開這把鎖
[condition lock];多用于多線程同時訪問本鸣、修改同一個數(shù)據(jù)源,保證在同一時間內(nèi)數(shù)據(jù)源只被訪問硅蹦、修改一次,其他線程
要在lock外等待闷煤,只到unlock才可訪問
[condition unlock];與lock 同時使用
[condition wait];讓當前線程處于等待狀態(tài)
[condition signal];CPU發(fā)信號告訴線程不用在等待童芹,可以繼續(xù)執(zhí)行
使用場1:景圖片消息:
當接受到圖片消息的時候,需要異步下載鲤拿,等到圖片下載完成之后假褪,同步數(shù)據(jù)庫,方可通知前端更新UI近顷。此時就需要使用
NSCondition 的wait
使用場2:數(shù)據(jù)加載上傳:
位置變化收集經(jīng)緯度數(shù)據(jù)生音,當達到500個點時上傳服務器成功后清空(當然這里還有中間層數(shù)據(jù)中轉)。此時就需要使用
NSCondition 的wait
窒升,方可通知前端更新UI缀遍。此時就需要使用
NSCondition 的wait
**/
- (void)sellTickets3
{
NSCondition *condition = [[NSCondition alloc] init];
NSMutableArray *products = [NSMutableArray array];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while (1) {
[condition lock];
if ([products count] < self.leftTicketsCount) {
NSLog(@"等待經(jīng)緯度數(shù)據(jù)收集...");
[condition wait];
}else{
NSLog(@"經(jīng)緯度數(shù)據(jù)滿載處理");
[products removeAllObjects];
}
[condition unlock];
}
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while (1) {
[condition lock];
[products addObject:@"+1"];
NSLog(@"經(jīng)緯度數(shù)據(jù),點個數(shù):%zi",products.count);
[condition signal];
[condition unlock];
sleep(1);
}
});
}
/**
4 NSConditionLock 條件鎖 2
**/
- (void)sellTickets4
{
NSMutableArray *products = [NSMutableArray array];
NSConditionLock *lock = [[NSConditionLock alloc]init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while (1) {
[lock lockWhenCondition:0];
for (int i=0; i<self.leftTicketsCount; i++) {
sleep(1);
[products addObject:@"+1"];
NSLog(@"正在收集經(jīng)緯度數(shù)據(jù)...,點個數(shù):%zi",products.count);
[self logGetStr:[NSString stringWithFormat:@"正在收集經(jīng)緯度數(shù)據(jù)...,點個數(shù):%zi",products.count]];
}
[lock unlockWithCondition:[products count]];
sleep(1);
}
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while (1) {
NSLog(@"等待經(jīng)緯度數(shù)據(jù)收集...");
[self logGetStr:[NSString stringWithFormat:@"等待經(jīng)緯度數(shù)據(jù)收集..."]];
[lock lockWhenCondition:self.leftTicketsCount];
[products removeAllObjects];
NSLog(@"經(jīng)緯度數(shù)據(jù)收集滿載處理");
[self logGetStr:[NSString stringWithFormat:@"經(jīng)緯度數(shù)據(jù)收集滿載處理"]];
[lock unlockWithCondition:[products count]];
}
});
}
/**
5. NSRecursiveLock 遞歸鎖
NSRecursiveLock 遞歸鎖 主要用在循環(huán)或遞歸操作中,它可以被同一線程多次請求,而不會引起死鎖饱须。
<NSLock>這是一個典型的死鎖情況域醇。在我們的線程中,recursionMethod是遞歸調(diào)用。所以每次進入這個block時譬挚,都會去加一次
鎖锅铅,從第二次開始,由于鎖已經(jīng)被使用并且沒有解鎖减宣,所以它要等待鎖被解除盐须,這樣就導致了死鎖,線程被阻塞住了漆腌。
bugLog輸出如下信息:
*** -[NSLock lock]: deadlock (<NSLock: 0x1740daf60> '(null)')
*** Break on _NSLockError() to debug.
<NSRecursiveLock>換成遞歸鎖一切正常了
**/
- (void)sellTickets5
{
// NSLock *recursiveLock = [[NSLock alloc] init];
NSRecursiveLock *recursiveLock = [[NSRecursiveLock alloc] init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
static void (^recursionMethod)(int);
recursionMethod = ^(int value) {
[recursiveLock lock];
if (value > 0) {
NSLog(@"value = %d", value);
[self logGetStr:[NSString stringWithFormat:
@"value = %d", value]];
sleep(1);
recursionMethod(value - 1);
}
[recursiveLock unlock];
};
recursionMethod(5);
});
}
/**
6. pthread_mutex 互斥鎖(C語言)
c語言定義下多線程加鎖方式贼邓。
1:pthread_mutex_init(pthread_mutex_t mutex,const pthread_mutexattr_t attr);
初始化鎖變量mutex。attr為鎖屬性屉凯,NULL值為默認屬性立帖。
2:pthread_mutex_lock(pthread_mutex_t mutex);加鎖
3:pthread_mutex_tylock(*pthread_mutex_t *mutex);加鎖,當鎖已經(jīng)在使用的時候悠砚,返回為
EBUSY晓勇,而不是掛起等待。
4:pthread_mutex_unlock(pthread_mutex_t *mutex);釋放鎖
5:pthread_mutex_destroy(pthread_mutex_t* mutex);使用完后釋放
**/
- (void)sellTickets6
{
__block pthread_mutex_t theLock;
pthread_mutex_init(&theLock, NULL);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
pthread_mutex_lock(&theLock);
NSLog(@"電腦開機...");
sleep(1);
NSLog(@"輸入密碼...");
pthread_mutex_unlock(&theLock);
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(2);
pthread_mutex_lock(&theLock);
NSLog(@"進入桌面");
pthread_mutex_unlock(&theLock);
});
}
/**
7. pthread_mutex(recursive) 互斥鎖(C語言)2
**/
-(void)sellTickets7
{
__block pthread_mutex_t theLock;
// pthread_mutex_init(&theLock, NULL);
pthread_mutex_t Mutex;
pthread_mutexattr_t Attr;
pthread_mutexattr_init(&Attr);
pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&Mutex, &Attr);
pthread_mutexattr_destroy(&Attr);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
static void (^recursionMethod)(int);
recursionMethod = ^(int value) {
pthread_mutex_lock(&theLock);
if (value > 0) {
NSLog(@"value = %d", value);
sleep(1);
recursionMethod(value - 1);
}
pthread_mutex_unlock(&theLock);
};
recursionMethod(self.leftTicketsCount);
});
}
/**
8. dispatch_semaphore 信號量實現(xiàn)加鎖(GCD)
dispatch_semaphore是GCD用來同步的一種方式灌旧,與他相關的共有三個函數(shù)绑咱,分別是
dispatch_semaphore_create,
dispatch_semaphore_signal枢泰,dispatch_semaphore_wait描融。
**/
-(void)sellTickets8
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (int i = 0; i < self.leftTicketsCount0; i++)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
int count=self.leftTicketsCount;
if (count>0) {
//休眠一段時間
sleep(1);
//2.票數(shù)-1
self.leftTicketsCount= count-1;
NSThread *current=[NSThread currentThread];
//獲取當前線程
NSLog(@"%@--賣了一張票,還剩余%d張票",current,self.leftTicketsCount);
}
dispatch_semaphore_signal(semaphore);
});
}
});
NSLog(@"我是主線程");
}
/**
9. OSSpinLock 自旋鎖:饴臁A恕!C住D甓!(已不安全不推薦使用,謹慎使用)
OSSpinLock 自旋鎖,性能最高的鎖.因為其是一直等待狀態(tài)玻募,因此對CUP要求很高只损,消耗大量CPU資源
不適宜長時使用,耗電七咧,好資源發(fā)熱高
OSSpinLock已經(jīng)不再安全@"http://blog.ibireme.com/2016/01/16/spinlock_is_unsafe_in_ios/"
**/
- (void)sellTickets9
{
__block OSSpinLock theLock = OS_SPINLOCK_INIT;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
OSSpinLockLock(&theLock);
NSLog(@"電腦開機...");
sleep(2);
NSLog(@"輸入密碼...");
OSSpinLockUnlock(&theLock);
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
OSSpinLockLock(&theLock);
sleep(1);
NSLog(@"進入桌面");
OSSpinLockUnlock(&theLock);
});
}
-(void)buttonClicked:(UIButton*)btAction
{
[mutLogStr setString:[NSString stringWithFormat:@"** %@\n",[nameArray objectAtIndex:btAction.tag-1]]];
self.leftTicketsCount = 5;
self.leftTicketsCount0 = 5;
if (btAction.tag<=2) {//1. @synchronized 關鍵字加鎖
SEL selector = NSSelectorFromString([_methodsArr objectAtIndex:btAction.tag-1]);
[self meathodGet:selector];
}else{
SEL selector = NSSelectorFromString([_methodsArr objectAtIndex:btAction.tag-1]);
[self performSelector:selector];
}
}
/**
一千萬次線程鎖空操作性能對比-sellTickets10
**/
- (void)sellTickets10{
NSMutableDictionary *sortDic = [[NSMutableDictionary alloc]init];
NSString *timestr;
CFTimeInterval timeBefore;
CFTimeInterval timeCurrent;
NSUInteger i;
NSUInteger count = 1000*10000;//執(zhí)行一千萬次
//OSSpinLockLock自旋鎖 T颈埂!0啊1妗!(已不安全)CFAbsoluteTimeGetCurrent
OSSpinLock spinlock = OS_SPINLOCK_INIT;
timeBefore = CACurrentMediaTime();
for(i=0; i<count; i++){
OSSpinLockLock(&spinlock);
OSSpinLockUnlock(&spinlock);
}
timeCurrent = CACurrentMediaTime();
timestr = [NSString stringWithFormat:@"%f",timeCurrent-timeBefore];
[sortDic setValue:@"OSSpinLock" forKey:timestr];
//@synchronized關鍵字加鎖
id obj = [[NSObject alloc]init];;
timeBefore = CACurrentMediaTime();
for(i=0; i<count; i++){
@synchronized(obj){
}
}
timeCurrent = CACurrentMediaTime();
timestr = [NSString stringWithFormat:@"%f",timeCurrent-timeBefore];
[sortDic setValue:@"@synchronized" forKey:timestr];
//NSLock對象鎖
NSLock *lock = [[NSLock alloc]init];
timeBefore = CACurrentMediaTime();
for(i=0; i<count; i++){
[lock lock];
[lock unlock];
}
timeCurrent = CACurrentMediaTime();
timestr = [NSString stringWithFormat:@"%f",timeCurrent-timeBefore];
[sortDic setValue:@"NSLock" forKey:timestr];
//NSCondition條件鎖1
NSCondition *condition = [[NSCondition alloc]init];
timeBefore = CACurrentMediaTime();
for(i=0; i<count; i++){
[condition lock];
[condition unlock];
}
timeCurrent = CACurrentMediaTime();
timestr = [NSString stringWithFormat:@"%f",timeCurrent-timeBefore];
[sortDic setValue:@"NSCondition" forKey:timestr];
//NSConditionLock條件鎖2
NSConditionLock *conditionLock = [[NSConditionLock alloc]init];
timeBefore = CACurrentMediaTime();
for(i=0; i<count; i++){
[conditionLock lock];
[conditionLock unlock];
}
timeCurrent = CACurrentMediaTime();
timestr = [NSString stringWithFormat:@"%f",timeCurrent-timeBefore];
[sortDic setValue:@"NSConditionLock" forKey:timestr];
//NSRecursiveLock遞歸鎖
NSRecursiveLock *recursiveLock = [[NSRecursiveLock alloc]init];
timeBefore = CACurrentMediaTime();
for(i=0; i<count; i++){
[recursiveLock lock];
[recursiveLock unlock];
}
timeCurrent = CACurrentMediaTime();
timestr = [NSString stringWithFormat:@"%f",timeCurrent-timeBefore];
[sortDic setValue:@"NSRecursiveLock" forKey:timestr];
//pthread_mutex互斥鎖1(C語言)
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
timeBefore = CACurrentMediaTime();
for(i=0; i<count; i++){
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
}
timeCurrent = CACurrentMediaTime();
timestr = [NSString stringWithFormat:@"%f",timeCurrent-timeBefore];
[sortDic setValue:@"pthread_mutexpthread_mutex" forKey:timestr];
//pthread_mutex(recursive)互斥鎖2(C語言)
pthread_mutex_t lockrecursive;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&lockrecursive, &attr);
pthread_mutexattr_destroy(&attr);
timeBefore = CACurrentMediaTime();
for (int i = 0; i < count; i++) {
pthread_mutex_lock(&lockrecursive);
pthread_mutex_unlock(&lockrecursive);
}
timeCurrent = CACurrentMediaTime();
timestr = [NSString stringWithFormat:@"%f",timeCurrent-timeBefore];
[sortDic setValue:@"pthread_mutex(recursive)" forKey:timestr];
//dispatch_semaphore信號量實現(xiàn)加鎖(GCD)
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
timeBefore = CACurrentMediaTime();
for(i=0; i<count; i++){
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_semaphore_signal(semaphore);
}
timeCurrent = CACurrentMediaTime();
timestr = [NSString stringWithFormat:@"%f",timeCurrent-timeBefore];
[sortDic setValue:@"dispatch_semaphore" forKey:timestr];
DEBUGLog(@"sortDic===%@",sortDic);
NSArray *resultArray = [[sortDic allKeys] sortedArrayUsingComparator:sort];
NSMutableAttributedString *contentForgeta = [[NSMutableAttributedString alloc]initWithString:mutLogStr];
for (int i=0;i<[resultArray count];i++) {
NSMutableAttributedString *contentForget = [[NSMutableAttributedString alloc]initWithString:[NSString stringWithFormat:@"** %i.%@----%@\n",i+1,[sortDic objectForKey:[resultArray objectAtIndex:i]],[resultArray objectAtIndex:i]]];
NSRange contentRange = {contentForget.length-9,8};
[contentForget addAttribute:NSForegroundColorAttributeName
value:[UIColor redColor]
range:contentRange];
[contentForget addAttribute:NSUnderlineStyleAttributeName
value:[NSNumber numberWithInteger:NSUnderlineStyleSingle]
range:contentRange];
[contentForgeta appendAttributedString:contentForget];
}
lab.attributedText = contentForgeta;
DEBUGLog(@"%@",lab.text);
}
-(void)logGetStr:(NSString*)logStr
{
[mutLogStr appendString:[NSString stringWithFormat:@"** %@\n",logStr]];
dispatch_async(dispatch_get_main_queue(), ^{
lab.text = mutLogStr;
});
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
GitHub地址:https://github.com/Yjunjie/MultithreadingAndLock/tree/master