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张---火车票
したがって、アクセスするには . 構文を使用する必要があります。ただし、アトミックは完全にスレッドセーフというわけではありません_totalTicket--
は、次のように setter getter メソッドを介さずにインスタンス変数を直接操作し、属性にアトミック属性を追加します。これは、スレッドの安全性を確保するために属性の読み書き時にロックされます # 🎜🎜# リーリー関連情報
ああ。ご回答ありがとうございます。このアトミックはちょっと物足りない気がします。よく見てますよ。ありがとう!