多线程同步?这个有什么意义呢。
多线程编程里面,一些敏感数据不允许被多个线程同时访问,此时就使用同步访问技术,保证数据在任何时刻,最多有一个线程访问,以保证数据的完整性。
先来个概念性的东西,理解下
信号量
信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。为了完成这个过程,需要创建一个信号量VI,然后将Acquire Semaphore VI以及Release Semaphore VI分别放置在每个关键代码段的首末端。确认这些信号量VI引用的是初始创建的信号量。
可以简单理解成线程同步作用和加锁相似。其实同步和加锁是有区别的。只是线程同步的效果和加锁之后的作用一样。具体下一篇会有解释。不废话了,直奔代码
先模拟用户去买票,一共提供三条通道,买票。
没有进行线程同步
上述是开启三条线程,然后都是同时去对数据进行减减操作。会发现,数据出现异常。那是因为,多条线程同时访问这个数据时候,该线程只是读取到他访问时候的数据,若此时还有其他线程对该数据进行操作的话。则这个数据就会出现异常。
一:GCD中的信号量实现线程同步
- (void)viewDidLoad {
[super viewDidLoad];
// 实例类person
self.person = [[Person alloc] init];
self.person.num = 100;
//dispatch_semaphore_create(1) 创建一个信号量,设置信号量的资源数0表示没有资源,调用dispatch_semaphore_wait会立即等待。
//dispatch_semaphore_signal 发送一个信号会让信号量+1
//dispatch_semaphore_wait 等待信号会让信号量 —1
self.semaphore = dispatch_semaphore_create(1);
//模拟三条不同的网络去抢票
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timeActionA) userInfo:nil repeats:YES];
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(timeActionB) userInfo:nil repeats:YES];
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timeActionC) userInfo:nil repeats:YES];
}
- (void)timeActionA{
// 线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//等待信号,当信号总量少于0的时候就会一直等待,否则就可以正常的执行,并让信号总量-1
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
[self.person personA];
//发送一个信号,自然会让信号总量加1,
dispatch_semaphore_signal(self.semaphore);
});
}
- (void)timeActionB{
// 线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
[self.person personB];
dispatch_semaphore_signal(self.semaphore);
});
}
- (void)timeActionC{
// 线程A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
[self.person personC];
dispatch_semaphore_signal(self.semaphore);
});
}
Person类的实现。
-(void)personA{
self.num--;
NSLog(@"A票通道 剩余总票:%ld",(long)self.num);}
-(void)personB{
self.num--;
NSLog(@"B票通道 剩余总票:%ld",(long)self.num);
}
-(void)personC{
self.num--;
NSLog(@"C票通道 剩余总票:%ld",(long)self.num);
}
一:GCD分组实现线程同步
- (void)viewDidLoad {
[super viewDidLoad];
// 实例类person
self.person = [[Person alloc] init];
self.person.num = 100;
//创建队列组队
self.group = dispatch_group_create();
//模拟三条不同的网络去抢票
[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(timeActionA) userInfo:nil repeats:YES];
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(timeActionB) userInfo:nil repeats:YES];
[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(timeActionC) userInfo:nil repeats:YES];
}
- (void)timeActionA{
//进入组
dispatch_group_enter(self.group);
//线程放进队列组
dispatch_group_async(self.group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.person personA];
//离开组
dispatch_group_leave(self.group);
});
}
- (void)timeActionB{
//进入组
dispatch_group_enter(self.group);
dispatch_group_async(self.group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.person personB];
dispatch_group_leave(self.group);
});
}
- (void)timeActionC{
//进入组
dispatch_group_enter(self.group);
dispatch_group_async(self.group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.person personC];
dispatch_group_leave(self.group);
});
}