objective-c - I would like to ask some questions about the understanding of the atomic keyword of @property.
大家讲道理
大家讲道理 2017-05-02 09:29:14
0
2
595

1. When learning multi-thread safety, I learned to use synchronization locks to avoid "simultaneous" access to the same resource when multiple threads execute concurrently. I remembered that when I was learning atomic before, I remembered that this keyword is used to set whether the property is thread-safe. So I turned off the synchronization lock in the program and used the above keywords to define the property. However, after performing multi-threaded operations, I found that this setting did not achieve thread safety. May I ask where my understanding is wrong?

My program code is as follows:

#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

The following is part of the output: Please note that two 98 are output

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张---火车票
大家讲道理
大家讲道理

光阴似箭催人老,日月如移越少年。

reply all(2)
小葫芦

_totalTicket--It operates the instance variables directly without going through the setter and getter methods, and adds the atomic attribute, which will lock the attribute when reading and writing it to ensure thread safety, as follows

atomic的实现:
- (void)setCurrentImage:(UIImage *)currentImage
{
    @synchronized(self) {
        if (_currentImage != currentImage) {
            [_currentImage release];
            _currentImage = [currentImage retain];
                    
            // do something
        }
    }
}

- (UIImage *)currentImage
{
    @synchronized(self) {
        return _currentImage;
    }
}

So you should use . syntax to access. But atomic is not absolutely thread-safe
Related information

我想大声告诉你

Oh. Thank you for your answer. I feel that this atomic is a bit unsatisfactory. I'm taking a good look. Thank you!

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template