iOS中有哪些技术可以保证线程安全?
1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源,比如多个线程访问同一个对象、同一个变量、同一个文件。当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题。此时,我们需要用线程锁来解决。
线程数据安全的方法:
1、nonatomic atomic:使用atomic多线程原子性控制,atomic的原理给setter加上锁,getter不会加锁。OC在定义属性时有nonatomic和atomic两种选择
atomic:原子属性,为setter方法加锁(默认就是atomic)
nonatomic:非原子属性,不会为setter方法加锁
#import "YYViewController.h"
@interface YYViewController ()
//剩余票数
@property(nonatomic,assign) int leftTicketsCount;
@property(nonatomic,strong)NSThread *thread1;
@property(nonatomic,strong)NSThread *thread2;
@property(nonatomic,strong)NSThread *thread3;
@end
@implementation YYViewController
- (void)viewDidLoad28
{
[super viewDidLoad];
//默认有10张票
self.leftTicketsCount=10;
//开启多个线程,模拟售票员售票
self.thread1=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil];
self.thread1.name=@"售票员A";
self.thread2=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil];
self.thread2.name=@"售票员B";
self.thread3=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil];
self.thread3.name=@"售票员C";
[self.thread1 start];
[self.thread2 start];
[self.thread3 start];
}
-(void)sellTickets
{
while (true)
{
if (self.leftTicketsCount > 0 )
{
[NSThread sleepForTimeInterval:0.5];
self.leftTicketsCount--;
NSLog(@"thread:%@ ---> %ld",[[NSThread currentThread] name],self.leftTicketsCount);
}
else
{
break;
}
}
}
2、使用GCD实现atomic操作:给某字段的setter和getter方法加上同步队列:
- (void)setCount:(NSInteger)newcount
{
dispatch_sync(_synQueue, ^{
count = newcount;
});
}
- (NSInteger)count
{
__block NSInteger localCount;
dispatch_sync(_synQueue, ^{
localCount = count;
});
return localCount;
}
3、 使用NSLock
- (void)threadRunLock
{
_lock = [[NSLock alloc]init];
while (true)
{
[_lock lock];
if (self.number > 0 )
{
[NSThread sleepForTimeInterval:0.5];
self.number --;
NSLog(@"thread:%@ ---> %ld",[[NSThread currentThread] name],self.number);
}
[_lock unlock];
}
}
相当于给代码片段加上lock了,所以依次输出9-0
4、使用互斥锁
使用格式
@synchronized(锁对象) { // 需要锁定的代码 }
注意:锁定1份代码只用1把锁,用多把锁是无效的
-(void)sellTickets
{
while (true)
{
@synchronized(self)
{
//只能加一把锁
//1.先检查票数
int count=self.leftTicketsCount;
if (count>0)
{
//暂停一段时间
[NSThread sleepForTimeInterval:0.002];
//2.票数-1
self.leftTicketsCount= count-1;
//获取当前线程
NSThread *current=[NSThread currentThread];
NSLog(@"%@--卖了一张票,还剩余%d张票",current,self.leftTicketsCount);
}
else
{
//退出线程
[NSThread exit];
}
}
}
}
互斥锁的优缺点:
优点:能有效防止因多线程抢夺资源造成的数据安全问题
缺点:需要消耗大量的CPU资源
互斥锁的使用前提:
多条线程抢夺同一块资源
相关专业术语:
线程同步,多条线程按顺序地执行任务。互斥锁,就是使用了线程同步技术