atomic
@property (atomic,assign) int age;
意味着这个属性是原子性操作,也就是保证setter
和gette
r是线程同步的.
static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy)
{
if (offset == 0) {
object_setClass(self, newValue);
return;
}
id oldValue;
id *slot = (id*) ((char*)self + offset);
if (copy) {
newValue = [newValue copyWithZone:nil];
} else if (mutableCopy) {
newValue = [newValue mutableCopyWithZone:nil];
} else {
if (*slot == newValue) return;
newValue = objc_retain(newValue);
}
if (!atomic) {
oldValue = *slot;
*slot = newValue;
} else {
spinlock_t& slotlock = PropertyLocks[slot];
slotlock.lock();
oldValue = *slot;
*slot = newValue;
slotlock.unlock();
}
objc_release(oldValue);
}
源码上来看如果是atomic
,赋值的前后加了自旋锁spinlock
它并不能保证使用属性的过程是线程安全的.
MyPerson *person = [MyPerson new];
person.datas = [NSMutableArray new];
//如果这边不加锁,多线程情况下并不能保证线程同步.atomic仅保证了getter方法的线程同步.addObject方法不是线程同步
//加锁
[person.datas addObject:@"1"];
[person.datas addObject:@"2"];
[person.datas addObject:@"3"];
//解锁
IO操作
读写安全方案
- 同一时间.只能有一个线程进行写的操作
- 同一时间,允许有多个线程进行读的操作
- 同一时间,不允许既有写的操作又有读的操作
pthread_rwlock
:读写锁
dispatch_barrier_async
异步栅栏调用
@interface ViewController ()
@property (nonatomic,assign) pthread_rwlock_t lock;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
pthread_rwlock_init(&_lock, NULL);
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
for (int i = 0; i < 10; i++) {
dispatch_async(queue, ^{
[self read];
});
dispatch_async(queue, ^{
[self write];
});
}
}
- (void)read
{
pthread_rwlock_rdlock(&_lock);
sleep(1);
NSLog(@"%s",__func__);
pthread_rwlock_unlock(&_lock);
}
- (void)write
{
pthread_rwlock_wrlock(&_lock);
sleep(1);
NSLog(@"%s",__func__);
pthread_rwlock_unlock(&_lock);
}
@end
dispatch_barrier_sync
- 这个函数传入的并发队列必须是通过
dispatch_queue_create
创建的. - 如果传入的是个串行or全局的并发队列,效果等同于
dispatch_async
dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 50; i++) {
dispatch_async(queue2, ^{
[self read];
});
dispatch_async(queue2, ^{
[self read];
});
dispatch_async(queue2, ^{
[self read];
});
dispatch_barrier_sync(queue2, ^{
[self write];
});
}
- (void)read
{
// pthread_rwlock_rdlock(&_lock);
sleep(1);
NSLog(@"%s",__func__);
// pthread_rwlock_unlock(&_lock);
}
- (void)write
{
// pthread_rwlock_wrlock(&_lock);
sleep(1);
NSLog(@"%s",__func__);
// pthread_rwlock_unlock(&_lock);
}