==1.@synchronize==
- 用于单例创建,使多线程下保证唯一对象
- 代码块可用于数组中唯一线程读写
==2.atomic==
- 是对象的属性关键字,负责对象的原子性操作,不负责对象的使用
- atomic 系统会在生成的setter/getter方法里添加锁,但是这个锁仅仅是保证了setter/getter存取的安全,并不能保证数据结果正确
- A、B、C等多个线程都要操作同一个对象setter,D线程要getter这个对象的值,那么每个线程都成保证各自数据的完整性,但是D线程最后get到的值并不能确定。
==3.OSSpinlock==
自旋锁
循环等待访问,不释放当前资源,类似while(1),负责轻量级的+1,-1,如在引用计数的+1,-1操作
==4.NSRecursiveLock==
递归锁
为了解决NSLock在已加锁的情况下重复加锁,调用NSRecursiveLock的lock方法,可以使加锁之后仍然获取到锁,并且加锁。加锁解锁成对出现。解决多线程下递归方法的加锁。
==4.NSLock==
线程锁,为了解决线程同步问题
==5.dispatch_semaphore_t==
信号量,实现对线程同步,资源共享访问的信号量级锁
1.GCD信号量简介
//和GCD的group等用法一致,这个函数是创建一个dispatch_s`emaphore_类型的信号量
//并且创建的时候需要指定信号量的大小。
dispatch_semaphore_create(long value); // 创建信号量
//发送信号量。该函数会对信号量的值进行加1操作。
dispatch_semaphore_signal(dispatch_semaphore_t deem); // 发送信号量
//等待信号量。如果信号量值为0,那么该函数就会一直等待,也就是不返回(相当于阻塞当前线程)
//直到该函数等待的信号量的值大于等于1,该函数会对信号量的值进行减1操作,然后返回。
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); // 等待信号量
2.用信号量机制使异步线程完成同步操作
两个任务虽然是异步的,但仍需要同步执行
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
dispatch_group_t grp = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create("concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(grp, queue, ^{
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
NSLog(@"task1 begin : %@",[NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"task1 finish : %@",[NSThread currentThread]);
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
//先等待task1内的信号量 直到 task1 finish
});
dispatch_group_async(grp, queue, ^{
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
NSLog(@"task2 begin : %@",[NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"task2 finish : %@",[NSThread currentThread]);
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
});
dispatch_group_notify(grp, dispatch_get_main_queue(), ^{
NSLog(@"refresh UI");
});
}
3 阻塞请求线程
dispatch_async(queue, 0), ^{
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[网络请求:^{
//请求回调
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
});
//多个请求顺序执行
==6.dispatch_barrier_async和dispatch_barrier_sync==
栅栏方法,用GCD方式实现多读单写
dispatch_barrier_sync
需要等待栅栏执行完才会执行栅栏后面的任务
dispatch_barrier_async
无需等待栅栏执行完,会继续往下走(保留在队列里)
dispatch_async(queue, ^{
NSLog(@"----1-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----2-----%@", [NSThread currentThread]);
});
dispatch_barrier_async(queue, ^{
//会等待内部执行完才往下走
NSLog(@"----barrier-----%@", [NSThread currentThread]);
});
dispatch_barrier_sync(queue, ^{
//会等待内部执行完才往下走
NSLog(@"----barrier-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----3-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----4-----%@", [NSThread currentThread]);
});
线程安全的数组
- 对元素的获取增加dispatch_sync
如
- (id)objectAtIndex:(NSUInteger)index {
__block id item = nil;
dispatch_sync(self.readWriteQuene, ^{
if (index <= self.array.count - 1) {
item = [self.array objectAtIndex:index];
}
});
return item;
}
- (nullable id)getFirstObject {
__block id item = nil;
dispatch_sync(self.readWriteQuene, ^{
if (self.array.count > 0) {
item = [self.array objectAtIndex:0];
}
});
return item;
}
- (nullable id)getLastObject {
__block id item = nil;
dispatch_sync(self.readWriteQuene, ^{
NSUInteger size = self.array.count;
if (size > 0) {
item = self.array[size - 1];
}
});
return item;
}
- 对数组操作增加栅栏方法
//synchronized 效率最低
- (void)addObject:(id)anObject {
dispatch_barrier_async(self.readWriteQuene, ^{
[self.array addObject:anObject];
});
}
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index {
dispatch_barrier_async(self.readWriteQuene, ^{
[self.array insertObject:anObject atIndex:index];
});
}
//还有很多操作数组的方法如removeLastObject
网友评论