/**
- 常见多线程及其优劣
-
- pthread : 一套通用的多线程API,支持跨平台,使用难度大,基本不用;
-
- NSThread : 使用更加面对对象,可直接操作线程对象,偶尔使用;
-
- GCD : 用于替代NSThread,线程间通讯更加便捷,经常使用;
-
- NSOperation : 基于GCD,比GCD多了一些简单实用的功能,使用更加面对对象,经常使用 */
/**
- 常见的几种多线程锁及其常用场景
-
- @synchronized : 一般用于ObjC对象
-
- NSConditionLock : 条件锁(内部自带一个条件变量)
-
- NSCondition : 条件锁
-
- NSRecursiveLock : 递归锁
-
- pthread_mutex(recursive)
-
- NSLock : 低端锁
-
- pthread_mutex : C语言下多线程加锁方式
-
- dispatch_semaphore : 信号量( GCD 用来同步的一种方式)
-
- OSSpinLock : 自旋锁,ios 10之后废弃,使用os_unfair_lock代替 */
#import <Foundation/Foundation.h>
#import "pthread.h"
int main(int args , const char * argv[]) {
@autoreleasepool {
dispatch_queue_t queue = dispatch_queue_create("com.gcd.lock.queue", DISPATCH_QUEUE_CONCURRENT);
// 注 : NSLock锁
__block NSInteger nslock_number = 0;
NSLock *lock = [[NSLock alloc] init];
dispatch_apply(10, queue, ^(size_t idx) {
[lock lock];
if (idx%2 == 0) {
nslock_number ++;
}else {
nslock_number --;
}
NSLog(@"NSLock number %ld",nslock_number);
[lock unlock];
});
NSLog(@"NSLock number finally : %ld \n",nslock_number);
// 注 : synchronized
// 1. 只允许修饰Objective-C对象
__block NSNumber *sychronized_number = @(0);
dispatch_apply(10, queue, ^(size_t idx) {
@synchronized (sychronized_number) {
if (idx%2 == 0) {
sychronized_number = @(sychronized_number.integerValue + 1);
}else {
sychronized_number = @(sychronized_number.integerValue - 1);
}
}
NSLog(@"sychronized number %@",sychronized_number);
});
NSLog(@"sychronized number finally %@ \n",sychronized_number);
// 注 : NSCondition、NSConditionLock
/*
* 1. 加锁和解锁需要在同一线程
* 2. 可以设置加/解锁条件
* 3. 注意初始化时候设置响应条件,否自条件加锁将永远获取不到锁
* 4. NSCondition需要外部条件变量来设置条件锁,NSConditionLock则自带一个条件变量
*/
__block NSInteger condition_number = 0;
NSConditionLock *conditionLock = [[NSConditionLock alloc] initWithCondition:1];
dispatch_apply(10, queue, ^(size_t idx) {
[conditionLock lockWhenCondition:1];
if (idx%2 == 0) {
condition_number ++;
}else {
condition_number --;
}
NSLog(@"NSConditionLock number %ld",condition_number);
[conditionLock unlockWithCondition:1];
});
NSLog(@"NSConditionLock number finally : %ld \n",condition_number);
/*
* 注 : NSRecursiveLock
* 1. 递归锁可以被同一线程多次请求,而不会死锁。
*/
__block NSInteger recursive_number = 1;
NSRecursiveLock *recursive_lock = [[NSRecursiveLock alloc] init];
void(^RecursiveMethod)(NSInteger);
__weak __block void(^WeakRecursiveMethod)(NSInteger);
WeakRecursiveMethod = RecursiveMethod = ^(NSInteger value) {
[recursive_lock lock];
if (value%2 == 0) {
recursive_number --;
}else {
recursive_number ++;
}
if (recursive_number > 2) {
recursive_number--;
NSLog(@"recursive_number value => %ld", recursive_number);
sleep(1);
WeakRecursiveMethod(recursive_number);
}
NSLog(@"recursive_number ==> %ld", recursive_number);
[recursive_lock unlock];
};
dispatch_apply(10, queue, ^(size_t idx) {
RecursiveMethod(idx);
});
NSLog(@"recursive_number finally ==> %ld", recursive_number);
/*
* pthread_mutex : C语言下多线程加锁方式
* 1. Implicit declaration of function 'pthread_mutex_unlock' is invalid in C99 : 导入 pthread.h即可
)
*/
__block NSInteger pthread_number = 0;
__block pthread_mutex_t pthread_lock;
pthread_mutex_init(&pthread_lock,NULL);
dispatch_apply(10, queue, ^(size_t idx) {
pthread_mutex_lock(&pthread_lock);
if (idx %2 == 0) {
pthread_number --;
} else {
pthread_number ++;
}
NSLog(@"pthread_number ==> %ld", pthread_number);
pthread_mutex_unlock(&pthread_lock);
});
NSLog(@"pthread_number finally ==> %ld", pthread_number);
/*
* OSSpinLink : 自旋锁
*/
__block NSInteger osspin_number = 0;
__block OSSpinLock osspin_lock = OS_SPINLOCK_INIT;
dispatch_apply(1000, queue, ^(size_t idx) {
OSSpinLockLock(&osspin_lock);
if (idx %2 == 0) {
osspin_number --;
} else {
osspin_number ++;
}
NSLog(@"osspin_number ==> %ld", osspin_number);
OSSpinLockUnlock(&osspin_lock);
});
NSLog(@"osspin_number finally ==> %ld", osspin_number);
}
}
递归锁
NSRecursiveLock 是递归锁,他和 NSLock 的区别在于,NSRecursiveLock 可以在一个线程中重复加锁(反正单线程内任务是按顺序执行的,不会出现资源竞争问题),NSRecursiveLock 会记录上锁和解锁的次数,当二者平衡的时候,才会释放锁,其它线程才可以上锁成功。
NSRecursiveLock *lock = [[NSRecursiveLock alloc] init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
static void (^RecursiveBlock)(int);
RecursiveBlock = ^(int value) {
[lock lock];
if (value > 0) {
NSLog(@"value:%d", value);
RecursiveBlock(value - 1);
}
[lock unlock];
};
RecursiveBlock(2);
});
2016-08-19 14:43:12.327 ThreadLockControlDemo[1878:145003] value:2
2016-08-19 14:43:12.327 ThreadLockControlDemo[1878:145003] value:1
为了解决这个问题是为了解决什么问题?
如上面的示例,如果用 NSLock 的话,lock 先锁上了,但未执行解锁的时候,就会进入递归的下一层,而再次请求上锁,阻塞了该线程,线程被阻塞了,自然后面的解锁代码不会执行,而形成了死锁。而 NSRecursiveLock 递归锁就是为了解决这个问题