上篇多線程(三)我們看了多線程的安全隱患 以及各種鎖的簡單使用,接下來我們來看看鎖的比較、以及自旋鎖、互斥鎖比較 和讀寫安全方案等
代碼詳見 gitHub_Demo
各種鎖類別
鎖名字 | 鎖類別 | 特點 |
---|---|---|
OSSpinLock | 自旋鎖 | 等待鎖的線程會處于忙等(busy-wait)狀態(tài),一直占用CPU資源 |
os_unfair_lock | 互斥鎖 | 等待鎖的線程會處于休眠狀態(tài),并非忙等 |
pthread_mutex | 互斥鎖 | 等待鎖的線程會處于休眠狀態(tài) |
pthread_mutex – 遞歸 | 遞歸鎖 | 需要初始化鎖的屬性(attr) |
pthread_mutex –條件 | 條件鎖 | 需要設置等待條件(condition) |
NSLock | 互斥鎖 | 是對mutex鎖的簡單的封裝 |
NSRecursiveLock | 遞歸鎖 | 是對mutex遞歸鎖簡單的封裝 |
NSCondition | 條件鎖 | 是對mutex和cond的封裝 |
NSConditionLock | 條件鎖 | 是對NSCondition更進一步的封裝(可以設置具體的條件值) |
SerialQueue | GCD | 可以實現(xiàn)線程同步 |
dispatch_semaphore | GCD | 信號量 |
@synchronized | 互斥鎖 | 是對mutex遞歸鎖的封裝 |
pthread_rwlock | 讀寫鎖 | 多讀單寫 |
dispatch_barrier_async | GCD | 異步柵欄調用 |
... | ... | ... |
iOS線程同步方案性能比較
Multithreading_33.png
自旋鎖、互斥鎖比較
Multithreading_34.png
atomic
Multithreading_35.png
nonatomic和atomic
atom:原子,不可再分割的單
atomic:原子性
給屬性加上atomic修飾,可以保證屬性的setter和getter都是原子性操作,也就是保證setter和gette內部是線程同步的
// 加鎖
int a = 10;
int b = 20;
int c = a + b;
// 解鎖
如:
- (void)setName:(NSString *)name{
// 加鎖
_name = name;
// 解鎖
}
- (NSString *)name{
//加鎖
return _name;
// 解鎖
}
atomic所說的線程安全只是保證了getter和setter存取方法的線程安全,并不能保證整個對象是線程安全的
#import "ViewController_18.h"
@interface ViewController_18 ()
@property (atomic,assign)NSInteger age;
@end
@implementation ViewController_18
- (void)viewDidLoad {
[super viewDidLoad];
//線程A
dispatch_async(dispatch_get_global_queue(0, 0), ^{
for(int i=0;i<20;i++){
self.age = self.age+1;
NSLog(@"--1---age = %ld---%@",(long)self.age,[NSThread currentThread]);
}
});
//線程B
dispatch_async(dispatch_get_global_queue(0, 0), ^{
for(int i=0;i<20;i++){
self.age = self.age+1;
NSLog(@"--2---age = %ld---%@",(long)self.age,[NSThread currentThread]);
}
});
sleep(5);
NSLog(@"lastAge = %ld---%@",(long)self.age,[NSThread currentThread]);
}
@end
打印:
Multithreading[6412:538075] --2---age = 2---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 1---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538074] --1---age = 3---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 4---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538075] --2---age = 5---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 5---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 6---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 7---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538074] --1---age = 9---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 8---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 10---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 11---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 12---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 13---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 14---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 15---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 16---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 17---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 18---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538074] --1---age = 20---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 19---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 21---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 22---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 23---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 24---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 25---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 26---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 27---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 28---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 29---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 30---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 31---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 32---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 33---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 34---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 35---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 36---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538074] --1---age = 37---<NSThread: 0x600003e7f440>{number = 3, name = (null)}
Multithreading[6412:538075] --2---age = 38---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538075] --2---age = 39---<NSThread: 0x600003e70240>{number = 4, name = (null)}
Multithreading[6412:538035] lastAge = 39---<NSThread: 0x600003efed00>{number = 1, name = main}
發(fā)現(xiàn):有2個5
Multithreading_36.png
iOS中的讀寫安全方案
Multithreading_37.png
pthread_rwlock
Multithreading_38.png
#import "ViewController_19.h"
#import <pthread.h>
@interface ViewController_19 ()
@property (assign, nonatomic) pthread_rwlock_t lock;
@property (nonatomic,assign)int age;
@end
@implementation ViewController_19
- (void)viewDidLoad {
[super viewDidLoad];
// 初始化鎖
pthread_rwlock_init(&_lock, NULL);
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
for (int i = 0; i < 100; i++) {
dispatch_async(queue, ^{
[self read];
});
dispatch_async(queue, ^{
[self write];
});
}
sleep(5);
NSLog(@"%@--age=%d",[NSThread currentThread],self.age);
}
- (void)read {
pthread_rwlock_rdlock(&_lock);
NSLog(@"%s--%@--age=%d", __func__,[NSThread currentThread],self.age);
pthread_rwlock_unlock(&_lock);
}
- (void)write{
pthread_rwlock_wrlock(&_lock);
self.age+=1;
NSLog(@"%s--%@--age=%d", __func__,[NSThread currentThread],self.age);
pthread_rwlock_unlock(&_lock);
}
- (void)dealloc{
pthread_rwlock_destroy(&_lock);
}
@end
dispatch_barrier_async
Multithreading_39.png
#import "ViewController_20.h"
@interface ViewController_20 ()
@property (nonatomic,strong)dispatch_queue_t queue;
@end
@implementation ViewController_20
- (void)viewDidLoad {
[super viewDidLoad];
self.queue = dispatch_queue_create("rw_queue", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 10; i++) {
[self read];
[self read];
[self read];
[self write];
}
}
- (void)read {
dispatch_async(self.queue, ^{
sleep(1);
NSLog(@"read");
});
}
- (void)write{
dispatch_barrier_async(self.queue, ^{
sleep(1);
NSLog(@"write");
});
}
@end
Multithreading_40.png
友情鏈接: