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特質的屬性,會在對屬性讀寫的時候進行加鎖保證線程安全,如下
atomic的实现:
- (void)setCurrentImage:(UIImage *)currentImage
{
@synchronized(self) {
if (_currentImage != currentImage) {
[_currentImage release];
_currentImage = [currentImage retain];
// do something
}
}
}
- (UIImage *)currentImage
{
@synchronized(self) {
return _currentImage;
}
}
所以你應該用.語法去訪問。但atomic並不是絕對線程安全的
相關資料