iOS各种锁简介(上)
本篇文章主要介绍iOS中几种不同的锁的实现方式,既然是简介,这里不会涉及到原理上面的东西,主要还是如何使用。
在开始之前,我们先构建一个测试类,假设这个类是一个共享资源,提供两个方法method1和method2,假设method1和method2是互斥的,代码如下:
@implementation TestObject
- (void)method1 {
NSLog(@"%@",NSStringFromSelector(_cmd));
}
- (void)method2 {
NSLog(@"%@",NSStringFromSelector(_cmd));
}
@end
NSLock
NSLock是cocoa提供给我们最基本的锁对象,这个是最简单的一个锁,NSLock提供了lock和unlock两个方法,分别是加锁和解锁。NSLock内部实际是封装了pthread_mutex。使用方法很简单,代码如下:
- (void)lockDemo {
TestObject *obj = [[TestObject alloc] init];
NSLock *lock = [[NSLock alloc] init];
// 线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[lock lock];
[obj method1];
sleep(10);
[lock unlock];
});
// 线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
[lock lock];
[obj method2];
[lock unlock];
});
}
从打印结果可以看出,线程1获得锁之后,线程2会一直等待,直到线程1释放锁(unlock)之后才会执行。
@synchronized
@synchronized的使用方式很简单,先看代码:
- (void)synchronizedDemo {
TestObject *obj = [[TestObject alloc] init];
// 线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(obj) {
[obj method1];
sleep(10);
}
});
// 线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
@synchronized(obj) {
[obj method2];
}
});
}
跟NSLock加锁的结果一样,线程2也是等到线程1释放锁之后才执行。从代码中可以看出,@synchronized实现锁非常方便,注意:@synchronized指令中使用的obj为锁的唯一标识,只有标识相同的时候,才满足互斥。如果上述代码中线程2@synchronized(obj)中的标识和线程1的不一样,那么线程2不会被阻塞。
pthread_mutex_t
pthread_mutex_t是posix下的一个锁类型,如果熟悉linux c编程的话会对这个比较熟悉。在iOS下使用也是一样的,代码如下:
- (void)pthreadDemo {
TestObject *obj = [[TestObject alloc] init];
__block pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
pthread_mutex_lock(&mutex);
[obj method1];
sleep(5);
pthread_mutex_unlock(&mutex);
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
pthread_mutex_lock(&mutex);
[obj method2];
pthread_mutex_unlock(&mutex);
});
}
注意: 由于pthread_mutex_t是posix下的API,所以要引入相应的头文件#import <pthread.h>
dispatch_semaphore_t
dispatch_semaphore_t是GCD里面的一个信号量机制,也可以用来做线程同步。其相关的方法主要有:
dispatch_semaphore_t dispatch_semaphore_create(long value);
long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
long dispatch_semaphore_signal(dispatch_semaphore_t dsema);
dispatch_semaphore_create:创建一个新的信号量,value代表信号量资源的数量.
dispatch_semaphore_wait: 等待资源释放,如果此时dsema大于0,获得资源,继续执行,并将信号量减1。如果dsema=0,阻塞当前线程直到其他线程调dispatch_semaphore_signal释放信号量。如果一直等不到信号量,则到timeout之后再继续执行。
dispatch_semaphore_signal:释放一个资源。
使用代码如下:
- (void)semaphoreDemo {
TestObject *obj = [[TestObject alloc] init];
dispatch_semaphore_t semphore = dispatch_semaphore_create(1);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semphore, DISPATCH_TIME_FOREVER);
[obj method1];
sleep(5);
dispatch_semaphore_signal(semphore);
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
dispatch_semaphore_wait(semphore, DISPATCH_TIME_FOREVER);
[obj method2];
dispatch_semaphore_signal(semphore);
});
}
网友评论