1.在学习多线程安全的时候 学到了使用同步锁来避免多条线程并发执行时“同时”访问同一资源的情况。我想起了 之前学习atomic时,想起了该关键字是用来设置属性是否是线程安全的。于是我在程序中关闭了同步锁,并使用了上面的关键字来定义property 可是我在执行多线程操作后,发现这个设置并没有达到线程安全的效果。 请问是我的理解哪里出现了偏差了呢?
我的程序代码如下:
#import "ThreadSafeVC.h"
@interface ThreadSafeVC ()
//售票员01
@property (nonatomic, strong) NSThread *thread01;
//售票员02
@property (nonatomic, strong) NSThread *thread02;
//售票员03
@property (nonatomic, strong) NSThread *thread03;
//火车票
@property (atomic, assign) NSInteger totalTicket;
@end
@implementation ThreadSafeVC
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = @"线程安全";
_totalTicket = 100;//假设有100张火车票
[self createSubThreadsSaleTicket];
}
//创建子线程,售票
- (void)createSubThreadsSaleTicket
{
_thread01 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
_thread02 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
_thread03 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
[_thread01 setName:@"售票员01"];
[_thread02 setName:@"售票员02"];
[_thread03 setName:@"售票员03"];
//开启线程
[_thread01 start];
[_thread02 start];
[_thread03 start];
}
- (void)saleTicket
{
while (true)
{
//添加 互斥锁
// @synchronized (self)//这里有一个疑问 就是我将_totalTicket 设置成@property(atomic,xxxxx)的时候,关闭了这里的同步锁,发现依然线程不安全
// {
[NSThread sleepForTimeInterval:0.03];
if (_totalTicket > 0)
{
_totalTicket--;
NSLog(@"%----@---卖出了---%zd张---火车票", [NSThread currentThread].name, _totalTicket);
}
else
{
break;
}
// }
}
}
@end
下面是部分输出结果: 请留意输出了 两个 98
2016-08-28 19:25:04.893 GYBase[2527:39769] 售票员01---卖出了---99张---火车票
2016-08-28 19:25:04.893 GYBase[2527:39771] 售票员03---卖出了---98张---火车票
2016-08-28 19:25:04.893 GYBase[2527:39770] 售票员02---卖出了---98张---火车票
2016-08-28 19:25:04.925 GYBase[2527:39770] 售票员02---卖出了---96张---火车票
2016-08-28 19:25:04.925 GYBase[2527:39771] 售票员03---卖出了---96张---火车票
2016-08-28 19:25:04.925 GYBase[2527:39769] 售票员01---卖出了---95张---火车票
2016-08-28 19:25:04.957 GYBase[2527:39770] 售票员02---卖出了---94张---火车票
2016-08-28 19:25:04.958 GYBase[2527:39769] 售票员01---卖出了---93张---火车票
2016-08-28 19:25:04.958 GYBase[2527:39771] 售票员03---卖出了---92张---火车票
2016-08-28 19:25:04.987 GYBase[2527:39770] 售票员02---卖出了---91张---火车票
2016-08-28 19:25:04.989 GYBase[2527:39769] 售票员01---卖出了---90张---火车票
2016-08-28 19:25:04.989 GYBase[2527:39771] 售票员03---卖出了---89张---火车票
2016-08-28 19:25:05.017 GYBase[2527:39770] 售票员02---卖出了---88张---火车票
2016-08-28 19:25:05.019 GYBase[2527:39769] 售票员01---卖出了---87张---火车票
2016-08-28 19:25:05.019 GYBase[2527:39771] 售票员03---卖出了---86张---火车票
2016-08-28 19:25:05.052 GYBase[2527:39771] 售票员03---卖出了---84张---火车票
2016-08-28 19:25:05.052 GYBase[2527:39770] 售票员02---卖出了---84张---火车票
2016-08-28 19:25:05.052 GYBase[2527:39769] 售票员01---卖出了---83张---火车票
2016-08-28 19:25:05.082 GYBase[2527:39771] 售票员03---卖出了---82张---火车票
2016-08-28 19:25:05.082 GYBase[2527:39770] 售票员02---卖出了---82张---火车票
高洛峰2017-05-02 09:31:14
_totalTicket--
은 setter getter 메소드를 통하지 않고 인스턴스 변수를 직접 조작하고, 다음과 같이 스레드 안전성을 보장하기 위해 속성을 읽고 쓸 때 잠기는 원자 속성을 추가하는 것입니다
따라서 액세스하려면 . 구문을 사용해야 합니다. 그러나 Atomic은 스레드로부터 절대적으로 안전하지 않습니다
관련 정보