ios多线程之线程锁
1.@synchronized的用法
@synchronized(self)的用法:
@synchronized 的作用是创建一个互斥锁,保证此时没有其它线程对self对象进行修改。这个是objective-c的一个锁定令牌,防止self对象在同一时间内被其它线程访问,起到线程的保护作用。
@synchronized(锁对象){//需要锁定的代码}
注意:锁定一份代码只用一把锁,使用多把锁是无效的。
互斥锁的优缺点:
优点:能有效的防止因多线程抢夺资源造成的数据安全问题。
缺点:需要消耗大量的CPU资源
互斥锁的使用前提:多条线程使用同一块资源
专业术语:线程同步
线程同步的意思:多条线程在同一条线上执行(按顺序的执行任务)
互斥锁,就是使用了线程同步技术
例如:一个电影院,有3个售票员。一场电影的总数量固定。3个售票员售票时,要判断是非还有余票。
/** 售票员01 */
@property (nonatomic, strong) NSThread *thread01;
/** 售票员02 */
@property (nonatomic, strong) NSThread *thread02;
/** 售票员03 */
@property (nonatomic, strong) NSThread *thread03;
/** 票的总数 */
@property (nonatomic, assign) NSInteger ticketCount;
- (void)viewDidLoad {
[super viewDidLoad];
// self.locker = [[NSObject alloc] init];
self.ticketCount =100;
self.thread01 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket)object:nil];
self.thread01.name =@"售票员01";
self.thread02 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket)object:nil];
self.thread02.name =@"售票员02";
self.thread03 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket)object:nil];
self.thread03.name =@"售票员03";
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.thread01 start];
[self.thread02 start];
[self.thread03 start];
}
- (void)saleTicket{
while (1) {
@synchronized(self) {
// 先取出总数
NSInteger count = self.ticketCount;
if (count > 0) {
self.ticketCount = count -1;
NSLog(@"%@卖了一张票,还剩下%zd张", [NSThread currentThread].name, self.ticketCount);
}else {
NSLog(@"票已经卖完了");
break;
}
}
}
}
https://www.jianshu.com/p/73e390edb404 (关于@synchronized() 使用)
2、NSLock 互斥锁
// 创建锁
NSLock *personLock = [NSLock new];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[personLock lock]; // 加锁
//code
[NSThread sleepForTimeInterval:3]; // 线程休眠3秒
[personLock unlock]; // 解锁
});
3、NSRecursiveLock 递归锁
// 创建锁对象
NSRecursiveLock *personLock = [[NSRecursiveLock alloc] init];
// 创建递归方法
static void (^testCode)(int);
testCode = ^(int value) {
[personLock lock];
if (value > 0)
{
NSLog(@"递归0");
[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");
[personLock unlock];
});
4、NSConditionLock 条件锁
// 创建锁对象
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]; // 解锁
});
5、pthread_mutex 互斥锁
// 互斥锁
__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);
});
6、dispatch_semaphore 信号量
dispatch_semaphore_t lock = dispatch_semaphore_create(1); //传入的参数必须大于或者等于0,否则会返回Null
long wait = dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); //wait = 0,则表示不需要等待,直接执行后续代码;wait != 0,则表示需要等待信号或者超时,才能继续执行后续代码。lock信号量减一,判断是否大于0,如果大于0则继续执行后续代码;lock信号量减一少于或者等于0,则等待信号量或者超时。
//需要执行的代码
long signal = dispatch_semaphore_signal(lock); //signal = 0,则表示没有线程需要其处理的信号量,换句话说,没有需要唤醒的线程;signal != 0,则表示有一个或者多个线程需要唤醒,则唤醒一个线程。(如果线程有优先级,则唤醒优先级最高的线程,否则,随机唤醒一个线程。)
// 创建并设置信量
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); // 发送信号
});
//停车场demo
- (void)parkingAreaADemo {
//假设目前有3个停车位
dispatch_semaphore_t semaphore = dispatch_semaphore_create(3);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//有10辆车过来打算停车
for (NSInteger i = 1; i <= 10; i ++) {
dispatch_async(queue, ^{
NSInteger carId = i;
if (carId % 3 == 0) {
//这几位车主不愿意一直等待,所有设定一个能接受的等待时间
NSUInteger result = dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 8 * carId * NSEC_PER_SEC));
if (result != 0) {//超时,直接离开
NSLog(@"第%ld个车主不等了",carId);
}else {
NSLog(@"第%ld个车主在规定的时间内等到了车位,进入停车场",carId);
[NSThread sleepForTimeInterval:10];
dispatch_semaphore_signal(semaphore);
NSLog(@"第%ld个车主离开,有空位了",carId);
}
}else {
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"第%ld个车主进入停车场",carId);
[NSThread sleepForTimeInterval:10 + i * 10];
dispatch_semaphore_signal(semaphore);
NSLog(@"第%ld个车主离开,有空位了",carId);
}
});
}
}
//运行结果
2018-05-24 12:13:55.959 MultiThreadingDemo[1490:186763] 第3个车主离开,有空位了
2018-05-24 12:13:55.959 MultiThreadingDemo[1490:186860] 第4个车主进入停车场
2018-05-24 12:14:05.959 MultiThreadingDemo[1490:186764] 第1个车主离开,有空位了
2018-05-24 12:14:05.959 MultiThreadingDemo[1490:186861] 第5个车主进入停车场
2018-05-24 12:14:15.960 MultiThreadingDemo[1490:186766] 第2个车主离开,有空位了
2018-05-24 12:14:15.960 MultiThreadingDemo[1490:186862] 第6个车主在规定的时间内等到了车位,进入停车场
2018-05-24 12:14:25.962 MultiThreadingDemo[1490:186862] 第6个车主离开,有空位了
2018-05-24 12:14:25.962 MultiThreadingDemo[1490:186863] 第7个车主进入停车场
2018-05-24 12:14:45.966 MultiThreadingDemo[1490:186860] 第4个车主离开,有空位了
2018-05-24 12:14:45.966 MultiThreadingDemo[1490:186864] 第8个车主进入停车场
2018-05-24 12:14:57.961 MultiThreadingDemo[1490:186865] 第9个车主不等了
2018-05-24 12:15:05.964 MultiThreadingDemo[1490:186861] 第5个车主离开,有空位了
2018-05-24 12:15:05.964 MultiThreadingDemo[1490:186866] 第10个车主进入停车场
2018-05-24 12:15:45.968 MultiThreadingDemo[1490:186863] 第7个车主离开,有空位了
2018-05-24 12:16:15.972 MultiThreadingDemo[1490:186864] 第8个车主离开,有空位了
2018-05-24 12:16:55.971 MultiThreadingDemo[1490:186866] 第10个车主离开,有空位了
https://blog.csdn.net/u013404303/article/details/80093944
https://www.cnblogs.com/yajunLi/p/6274282.html
相关文章
网友评论