1、 @synchronized的使用介绍
1、底层是对互斥锁mutex的封装,一个对象一把锁
2、支持递归加锁
#import "SynchronizedVC.h"
@interface SynchronizedVC ()
@end
@implementation SynchronizedVC
- (void)viewDidLoad {
[super viewDidLoad];
[self concurrentMoney];
[self concurrentSaleTicket];
}
- (void)__saveMoney {
@synchronized (self) { // 加锁和解锁的对象要是同一个self
[super saveMoney];
}
}
- (void)__drawMoney {
@synchronized (self) { // 加锁和解锁的对象要是同一个self
[super drawMoney];
}
}
- (void)__saleTicket {
static NSObject *lockObj;
static dispatch_once_t onecToken;
dispatch_once(&onecToken, ^{
lockObj = [[NSObject alloc] init];
});
@synchronized (lockObj) { // 这里可以创建另外一个锁对象,用单例创建就可以了
[super saleTicket];
}
}
- (void)concurrentMoney {
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
for (int i = 0; i < 10; i++) {
[self __saveMoney];
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 10; i++) {
[self __drawMoney];
}
});
}
- (void)concurrentSaleTicket {
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
for (int i = 0; i < 5; i++) {
[self __saleTicket];
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 5; i++) {
[self __saleTicket];
}
});
}
@end
2、各种锁性能从高往低排列如下:
os_unfair_lock |
---|
OSSpinLock |
dispatch_semaphore |
pthread_mutex |
dispatch_queue(DISPATCH_QUEUE_SERIAL) |
NSLock |
NSCondition |
pthread_mutex(recursive) |
NSRecursiveLock |
NSConditionLock |
@synchronized |
3、自选锁、互斥锁比较
1、什么情况使用自旋锁比较划算
(1)预计线程等待锁的时间很短
(2)加锁的代码(临界区)经常被调用,但竞争情况很少发生
(3)CPU资源不紧张
(4)多核处理器
2、什么情况使用互斥锁比较划算
(1)预计线程等待锁的时间较长
(2)单核处理器
(3)临界区有IO操作
(4)临界区代码复杂或循环量大
(5)临界区竞争非常激烈
4、atomic补充
- atomic 只能保证属性的setter 方法 和getter方法是线程安全的,这样不仅消耗大量性能,而且在其他使用的时候,仍然无法保证线程安全的。
- 就算想要在setter方法和getter方法来保证性能安全,大可以在调用的地方加锁来用其他方式保证线程安全,完全没必要对setter、getter方法内部进行加锁,所以说,一般都是用noatomic.