线程互斥:保证共享数据每次只能被一个线程访问,具有排他性.
多线程并发执行时,访问共享数据时是无序的.当多个线程同时访问(修改)同一个数据时,可能会出现数据错乱现象.此时需要线程互斥,而线程互斥需要一个互斥锁
互斥锁:当某个线程访问共享数据时,需要枷锁,其他线程则处于等待状态;访问数据结束时,需要解锁,所有线程可以继续访问数据.
这里以典型实例火车票系统说明:
1.首先定义三个实例变量:
int _totalCount; //火车票总数量
<pre name="code" class="objc"><pre name="code" class="objc"> int _shengyuCount; //剩余票数
<span style="font-size:18px;"></span><pre name="code" class="objc"> NSLock *_lock; //互斥锁,用于实现线程互斥
2.设置剩余票数为100张,不同的火车站,或者代售点为不同的线程
//设置剩余票数为100张
_shengyuCount = 100;
//创建锁
_lock = [[NSLock alloc]init];
//线程1:火车站
NSThread * thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTickets) object:nil];
thread1.name = @"火车站";
[thread1 start];
//线程2:代售点
NSThread * thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTickets) object:nil];
thread2.name = @"代售点";
[thread2 start];
3.现在开始卖票,卖票在不同的子线程中执行,每个线程卖票过程中需要加锁,卖票完成后解锁,并修改剩余票数
//卖票,在子线程中执行
-(void)saleTickets
{
while (_shengyuCount > 0) {
//使用互斥锁给对象上锁
[_lock lock];
//每运行一次暂停0.1秒
[NSThread sleepForTimeInterval:0.1];
//获取当前线程
NSThread *currentThread = [NSThread currentThread];
NSLog(@"当前火车票由 %@ 售出,余票: %d张",currentThread.name,_shengyuCount);
//修改剩余票数
_shengyuCount--;
//解锁
[_lock unlock];
}
}
下面给出完整代码 :
#import "ViewController.h"
@interface ViewController ()
{
int _totalCount; //火车票总数量
int _shengyuCount; //剩余票数
NSLock *_lock; //互斥锁,用于实现线程互斥
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//多线程并发执行时,访问共享数据时是无序的.当多个线程同时访问(修改)同一个数据时,可能会出现数据错乱现象.
//线程互斥:保证共享数据每次只能被一个线程访问,具有排他性.
//互斥锁:当某个线程访问共享数据时,需要枷锁,其他线程则处于等待状态;访问数据结束时,需要解锁,所有线程可以继续访问数据.
//设置剩余票数为100张
_shengyuCount = 100;
//创建锁
_lock = [[NSLock alloc]init];
//线程1:火车站
NSThread * thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTickets) object:nil];
thread1.name = @"火车站";
[thread1 start];
//线程2:代售点
NSThread * thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTickets) object:nil];
thread2.name = @"代售点";
[thread2 start];
}
//卖票,在子线程中执行
-(void)saleTickets
{
while (_shengyuCount > 0) {
//使用互斥锁给对象上锁
[_lock lock];
//每运行一次暂停0.1秒
[NSThread sleepForTimeInterval:0.1];
//获取当前线程
NSThread *currentThread = [NSThread currentThread];
NSLog(@"当前火车票由 %@ 售出,余票: %d张",currentThread.name,_shengyuCount);
//修改剩余票数
_shengyuCount--;
//解锁
[_lock unlock];
}
}