多線程(四)

上篇多線程(三)我們看了多線程的安全隱患 以及各種鎖的簡單使用,接下來我們來看看鎖的比較、以及自旋鎖、互斥鎖比較讀寫安全方案
代碼詳見 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

友情鏈接:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,406評論 6 538
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,034評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,413評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,449評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,165評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,559評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,606評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,781評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,327評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,084評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,278評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,849評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,495評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,927評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,172評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,010評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,241評論 2 375