您的位置:首页 > 移动开发 > IOS开发

iOS多线程编程——线程锁的使用

2018-03-07 14:47 375 查看
锁是多线程中中最常用的同步工具。
 在多线程编程中,不可避免的会遇到同一个资源在多个线程之间共同使用,这时候就需要通过加锁来保证线程的安全。
 1、@synchronized 互斥锁(性能较差;适用线程不多,任务量不大的多线程加锁)
 (1)加锁的代码尽量少
 (2)添加的OC对象必须在多个线程中都是同一对象
 (3)优点是不需要显式的创建锁对象,便可以实现锁的机制。
 (4)@synchronized块会隐式的添加一个异常处理例程来保护代码,该处理例程会在异常抛出的时候自动的释放互斥锁。所以如果不想让隐式的异常处理例程带来额外的开销,你可以考虑使用锁对象。
 2、NSLock 互斥锁(多次调用lock方法会造成死锁)
 (1)在Cocoa程序中NSLock中实现了一个简单的互斥锁。
 (2)所有锁(包括NSLock)的接口实际上都是通过NSLocking协议定义的,它定义了lock和unlock方法。你使用这些方法来获取和释放该锁。
 (3)NSLock类还增加了tryLock和lockBeforeDate:方法;tryLock试图获取一个锁,但是如果锁不可用的时候,它不会阻塞线程,相反,它只是返回NO。
 lockBeforeDate:方法试图获取一个锁,但是如果锁没有在规定的时间内被获得,它会让线程从阻塞状态变为非阻塞状态(或者返回NO)。
 3、NSRecursiveLock 递归锁(在递归或循环中使用递归锁;递归锁的性能出奇的高,但是只能作为递归使用,所以限制了使用场景)
 4、NSConditionLock 条件锁(加锁性能非常低,但是可以用来做多线程处理不同任务的通信调用)
 5、pthread_mutex 互斥锁(底层的api,复杂的多线程处理建议使用,并且可以封装自己的多线程)
 6、dispatch_semaphore 信号量@interface Person : NSObject

@property (nonatomic, strong) NSString *name;

- (void)showMessage;

@end

@implementation Person

- (void)showMessage
{
NSLog(@"%@, name is %@", [NSThread currentThread], self.name);
}

@end
- (void)threadSynchronized
{
// 互斥锁 @synchronized 的使用,锁定的对象为锁的唯一标识,只有标识相同时,才满足互斥。
NSLog(@"互斥锁");

Person *person = [Person new];
person.name = @"iosDev";

Person *person2 = [Person new];
person2.name = @"devZhang";

// 线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(person) {
[person showMessage];
[NSThread sleepForTimeInterval:3]; // 线程休眠3秒
}
});
// 线程B
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(person) {
[person showMessage];
}
});
// 线程C
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(person2) {
[person2 showMessage];
}
});
}
2018-03-07 14:43:43.972 DemoThread[1905:201544] <NSThread: 0x600000273380>{number = 9, name = (null)}, name is iosDev
2018-03-07 14:43:43.972 DemoThread[1905:201556] <NSThread: 0x608000275f80>{number = 10, name = (null)}, name is devZhang
2018-03-07 14:43:46.974 DemoThread[1905:194520] <NSThread: 0x600000273100>{number = 11, name = (null)}, name is iosDev

- (void)threadNSLock
{
// 互斥锁 NSLock 的使用,一个线程的执行需要等待另一个线程解锁后才开始。锁定(lock)和解锁(unLock)必须配对使用。
NSLog(@"互斥锁");

Person *person = [Person new];
person.name = @"iosDev";

Person *person2 = [Person new];
person2.name = @"devZhang";

// 创建锁
NSLock *personLock = [NSLock new];

// 线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(person) {
[personLock lock]; // 加锁
[person showMessage];
[NSThread sleepForTimeInterval:3]; // 线程休眠3秒
[personLock unlock]; // 解锁
}
});
// 线程B
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(person) {
[personLock lock]; // 加锁
[person showMessage];
[personLock unlock]; // 解锁
}
});
// 线程C
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(person2) {
[person2 showMessage];
}
});
}
2018-03-07 14:44:19.925 DemoThread[1905:201556] <NSThread: 0x608000275f80>{number = 10, name = (null)}, name is iosDev
2018-03-07 14:44:19.925 DemoThread[1905:202091] <NSThread: 0x608000274240>{number = 12, name = (null)}, name is devZhang
2018-03-07 14:44:22.930 DemoThread[1905:202090] <NSThread: 0x60800007e540>{number = 13, name = (null)}, name is iosDev

- (void)threadNSRecursiveLock
{
// 递归锁 NSRecursiveLock 的使用,在递归方法中使用递归锁,否则会造成死锁。
NSLog(@"递归锁");

Person *person = [Person new];
person.name = @"iosDev";

Person *person2 = [Person new];
person2.name = @"devZhang";

// 创建锁对象
NSRecursiveLock *personLock = [[NSRecursiveLock alloc] init];

// 创建递归方法
static void (^testCode)(int);
testCode = ^(int value) {
[personLock lock];
if (value > 0)
{
NSLog(@"递归0");
[person showMessage];
[NSThread sleepForTimeInterval:1];
testCode(value - 1);
}
[personLock unlock];
};

// 线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
testCode(5);
});
// 线程B
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[personLock lock];
NSLog(@"递归1");
[person showMessage];
[personLock unlock];
});
}

2018-03-07 14:44:47.007 DemoThread[1905:202091] 递归0
2018-03-07 14:44:47.007 DemoThread[1905:202091] <NSThread: 0x608000274240>{number = 12, name = (null)}, name is iosDev
2018-03-07 14:44:48.008 DemoThread[1905:202091] 递归0
2018-03-07 14:44:48.009 DemoThread[1905:202091] <NSThread: 0x608000274240>{number = 12, name = (null)}, name is iosDev
2018-03-07 14:44:49.012 DemoThread[1905:202091] 递归0
2018-03-07 14:44:49.013 DemoThread[1905:202091] <NSThread: 0x608000274240>{number = 12, name = (null)}, name is iosDev
2018-03-07 14:44:50.016 DemoThread[1905:202091] 递归0
2018-03-07 14:44:50.017 DemoThread[1905:202091] <NSThread: 0x608000274240>{number = 12, name = (null)}, name is iosDev
2018-03-07 14:44:51.019 DemoThread[1905:202091] 递归0
2018-03-07 14:44:51.019 DemoThread[1905:202091] <NSThread: 0x608000274240>{number = 12, name = (null)}, name is iosDev
2018-03-07 14:44:52.020 DemoThread[1905:202411] 递归1
2018-03-07 14:44:52.020 DemoThread[1905:202411] <NSThread: 0x608000274e40>{number = 14, name = (null)}, name is iosDev

- (void)threadCondition
{
// 条件锁 NSConditionLock 的使用,只有满足条件的时候才可以解锁。
NSLog(@"条件锁");

Person *person = [Person new];
person.name = @"iosDev";

Person *person2 = [Person new];
person2.name = @"devZhang";

// 创建锁对象
NSConditionLock *personLock = [[NSConditionLock alloc] init];

// 线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[personLock lock]; // 加锁
[person showMessage];
[NSThread sleepForTimeInterval:3];
[personLock unlockWithCondition:10]; // 符合条件时解锁
});
// 线程B
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[personLock lockWhenCondition:10]; // 符合条件时加锁
[person showMessage];
[personLock unlock]; // 解锁
});
}

2018-03-07 14:45:22.072 DemoThread[1905:202412] <NSThread: 0x608000272e80>{number = 15, name = (null)}, name is iosDev
2018-03-07 14:45:25.077 DemoThread[1905:202887] <NSThread: 0x608000274bc0>{number = 16, name = (null)}, name is iosDev

- (void)threadCMethod
{
// C语言方法实现加锁
// 互斥锁
// 互斥锁 + 条件锁
// #import <pthread.h>

Person *person = [Person new];
person.name = @"iosDev";

Person *person2 = [Person new];
person2.name = @"devZhang";

// 创建锁对象
NSLog(@"互斥锁");
// 互斥锁
__block pthread_mutex_t personlock;
pthread_mutex_init(&personlock, NULL);

// 线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
pthread_mutex_lock(&personlock); // 加锁
[person showMessage];
[NSThread sleepForTimeInterval:3];
pthread_mutex_unlock(&personlock); // 解锁
});
// 线程B
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
pthread_mutex_lock(&personlock);
[person showMessage];
pthread_mutex_unlock(&personlock);
});

NSLog(@"互斥锁 + 条件锁");
// 互斥锁 + 条件锁
__block pthread_cond_t personCodition;
pthread_cond_init(&personCodition, NULL);

// 线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
pthread_mutex_lock(&personlock); // 加锁
pthread_cond_wait(&personCodition, &personlock); // 条件锁
[person showMessage];
pthread_mutex_unlock(&personlock); // 解锁
});
// 线程B
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
pthread_mutex_lock(&personlock);
[person showMessage];
pthread_cond_signal(&personCodition); // 条件锁
[NSThread sleepForTimeInterval:3];
pthread_mutex_unlock(&personlock);
});
}

2018-03-07 14:46:07.545 DemoThread[1905:202888] <NSThread: 0x608000274c40>{number = 17, name = (null)}, name is iosDev
2018-03-07 14:46:10.548 DemoThread[1905:203469] <NSThread: 0x608000273c80>{number = 18, name = (null)}, name is iosDev
2018-03-07 14:46:10.548 DemoThread[1905:203471] <NSThread: 0x608000273dc0>{number = 19, name = (null)}, name is iosDev
2018-03-07 14:46:13.552 DemoThread[1905:203470] <NSThread: 0x608000273e80>{number = 20, name = (null)}, name is iosDev

- (void)threadGCD
{
// 使用 GCD 实现 “ 锁 ” (信号量)  GCD提供一种信号的机制,使用它我们可以创建“锁”(信号量和锁是有区别的,具体请自行百度)。

Person *person = [Person new];
person.name = @"iosDev";

Person *person2 = [Person new];
person2.name = @"devZhang";

// 创建并设置信量
dispatch_semaphore_t personGCD = dispatch_semaphore_create(1);

// 线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(personGCD, DISPATCH_TIME_FOREVER); // 等待信号
[person showMessage];
[NSThread sleepForTimeInterval:3];
dispatch_semaphore_signal(personGCD); // 发送信号
});
// 线程B
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(personGCD, DISPATCH_TIME_FOREVER); // 等待信号
[person showMessage];
dispatch_semaphore_signal(personGCD); // 发送信号
});
}

2018-03-07 14:46:41.194 DemoThread[1905:203472] <NSThread: 0x608000273dc0>{number = 21, name = (null)}, name is iosDev
2018-03-07 14:46:44.194 DemoThread[1905:203982] <NSThread: 0x608000274240>{number = 22, name = (null)}, name is iosDev
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息