iOS底層day9 - 多線程

進(jìn)程 & 線程

  • 提到線程,那就不得不提CPU,現(xiàn)代的CPU有一個很重要的特性,就是時間片,每一個獲得CPU的任務(wù)只能運(yùn)行一個時間片規(guī)定的時間。
  • 其實(shí)線程對操作系統(tǒng)來說就是一段代碼以及運(yùn)行時數(shù)據(jù)。操作系統(tǒng)會為每個線程保存相關(guān)的數(shù)據(jù),當(dāng)接收到來自CPU的時間片中斷事件時,就會按一定規(guī)則從這些線程中選擇一個,恢復(fù)它的運(yùn)行時數(shù)據(jù),這樣CPU就可以繼續(xù)執(zhí)行這個線程了。
  • 也就是其實(shí)就單核CUP而言,并沒有辦法實(shí)現(xiàn)真正意義上的并發(fā)執(zhí)行,只是CPU快速地在多條線程之間調(diào)度,CPU調(diào)度線程的時間足夠快,就造成了多線程并發(fā)執(zhí)行的假象。并且就單核CPU而言多線程可以解決線程阻塞的問題,但是其本身運(yùn)行效率并沒有提高,多CPU的并行運(yùn)算才真正解決了運(yùn)行效率問題。
  • 系統(tǒng)中正在運(yùn)行的每一個應(yīng)用程序都是一個進(jìn)程,每個進(jìn)程系統(tǒng)都會分配給它獨(dú)立的內(nèi)存運(yùn)行。也就是說,在iOS系統(tǒng)中中,每一個應(yīng)用都是一個進(jìn)程。
  • 一個進(jìn)程的所有任務(wù)都在線程中進(jìn)行,因此每個進(jìn)程至少要有一個線程,也就是主線程。那多線程其實(shí)就是一個進(jìn)程開啟多條線程,讓所有任務(wù)并發(fā)執(zhí)行。
  • 多線程在一定意義上實(shí)現(xiàn)了進(jìn)程內(nèi)的資源共享,以及效率的提升。同時,在一定程度上相對獨(dú)立,它是程序執(zhí)行流的最小單元,是進(jìn)程中的一個實(shí)體,是執(zhí)行程序最基本的單元,有自己棧和寄存器

同步異步 & 串行并行

同步與異步的區(qū)別:具不具備開線程的能力
串行與并行:可不可以同時執(zhí)行多個任務(wù),異步是多個任務(wù)并行的前提條件

舉個栗子 & 同步異步

    dispatch_queue_t queue = dispatch_queue_create("myquere", DISPATCH_QUEUE_SERIAL);
    dispatch_sync(queue, ^{
        for (int i = 0; i < 10; i ++) {
            NSLog(@"queue4 -- %d -----%@",i,[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 10; i ++) {
            NSLog(@"queue5 -- %d -----%@",i,[NSThread currentThread]);
        }
    });

打印結(jié)果

2018-11-07 08:51:58.130210+0800 09-線程[1136:19292] queue4 -- 0 -----<NSThread: 0x600000076240>{number = 1, name = main}
2018-11-07 08:51:58.130486+0800 09-線程[1136:19292] queue4 -- 1 -----<NSThread: 0x600000076240>{number = 1, name = main}
2018-11-07 08:51:58.130669+0800 09-線程[1136:19292] queue4 -- 2 -----<NSThread: 0x600000076240>{number = 1, name = main}
2018-11-07 08:51:58.130822+0800 09-線程[1136:19292] queue4 -- 3 -----<NSThread: 0x600000076240>{number = 1, name = main}
2018-11-07 08:51:58.131010+0800 09-線程[1136:19292] queue4 -- 4 -----<NSThread: 0x600000076240>{number = 1, name = main}
2018-11-07 08:51:58.131154+0800 09-線程[1136:19292] queue4 -- 5 -----<NSThread: 0x600000076240>{number = 1, name = main}
2018-11-07 08:51:58.131290+0800 09-線程[1136:19292] queue4 -- 6 -----<NSThread: 0x600000076240>{number = 1, name = main}
2018-11-07 08:51:58.131423+0800 09-線程[1136:19292] queue4 -- 7 -----<NSThread: 0x600000076240>{number = 1, name = main}
2018-11-07 08:51:58.131548+0800 09-線程[1136:19292] queue4 -- 8 -----<NSThread: 0x600000076240>{number = 1, name = main}
2018-11-07 08:51:58.132504+0800 09-線程[1136:19292] queue4 -- 9 -----<NSThread: 0x600000076240>{number = 1, name = main}
2018-11-07 08:51:58.133260+0800 09-線程[1136:19344] queue5 -- 0 -----<NSThread: 0x604000469880>{number = 3, name = (null)}
2018-11-07 08:51:58.133849+0800 09-線程[1136:19344] queue5 -- 1 -----<NSThread: 0x604000469880>{number = 3, name = (null)}
2018-11-07 08:51:58.174407+0800 09-線程[1136:19344] queue5 -- 2 -----<NSThread: 0x604000469880>{number = 3, name = (null)}
2018-11-07 08:51:58.174590+0800 09-線程[1136:19344] queue5 -- 3 -----<NSThread: 0x604000469880>{number = 3, name = (null)}
2018-11-07 08:51:58.175140+0800 09-線程[1136:19344] queue5 -- 4 -----<NSThread: 0x604000469880>{number = 3, name = (null)}
2018-11-07 08:51:58.175492+0800 09-線程[1136:19344] queue5 -- 5 -----<NSThread: 0x604000469880>{number = 3, name = (null)}
2018-11-07 08:51:58.176540+0800 09-線程[1136:19344] queue5 -- 6 -----<NSThread: 0x604000469880>{number = 3, name = (null)}
2018-11-07 08:51:58.176792+0800 09-線程[1136:19344] queue5 -- 7 -----<NSThread: 0x604000469880>{number = 3, name = (null)}
2018-11-07 08:51:58.176952+0800 09-線程[1136:19344] queue5 -- 8 -----<NSThread: 0x604000469880>{number = 3, name = (null)}
2018-11-07 08:51:58.177108+0800 09-線程[1136:19344] queue5 -- 9 -----<NSThread: 0x604000469880>{number = 3, name = (null)}

異步下,開啟了一個子線程number 3 去執(zhí)行任務(wù)

舉個栗子 & 串行并行

異步串行:

    dispatch_queue_t queue2 = dispatch_queue_create("myqueue", DISPATCH_QUEUE_SERIAL);
    for (int i = 0; i < 10; i ++) {
        dispatch_async(queue2, ^{
            NSLog(@"queue5 -- %d -----%@",i,[NSThread currentThread]);
        });
    }

執(zhí)行結(jié)果:

2018-11-07 09:13:22.052006+0800 09-線程[2109:42825] queue5 -- 0 -----<NSThread: 0x604000467940>{number = 3, name = (null)}
2018-11-07 09:13:22.052427+0800 09-線程[2109:42825] queue5 -- 1 -----<NSThread: 0x604000467940>{number = 3, name = (null)}
2018-11-07 09:13:22.052618+0800 09-線程[2109:42825] queue5 -- 2 -----<NSThread: 0x604000467940>{number = 3, name = (null)}
2018-11-07 09:13:22.052806+0800 09-線程[2109:42825] queue5 -- 3 -----<NSThread: 0x604000467940>{number = 3, name = (null)}
2018-11-07 09:13:22.053263+0800 09-線程[2109:42825] queue5 -- 4 -----<NSThread: 0x604000467940>{number = 3, name = (null)}
2018-11-07 09:13:22.053826+0800 09-線程[2109:42825] queue5 -- 5 -----<NSThread: 0x604000467940>{number = 3, name = (null)}
2018-11-07 09:13:22.053981+0800 09-線程[2109:42825] queue5 -- 6 -----<NSThread: 0x604000467940>{number = 3, name = (null)}
2018-11-07 09:13:22.054201+0800 09-線程[2109:42825] queue5 -- 7 -----<NSThread: 0x604000467940>{number = 3, name = (null)}
2018-11-07 09:13:22.054602+0800 09-線程[2109:42825] queue5 -- 8 -----<NSThread: 0x604000467940>{number = 3, name = (null)}
2018-11-07 09:13:22.054895+0800 09-線程[2109:42825] queue5 -- 9 -----<NSThread: 0x604000467940>{number = 3, name = (null)}

異步并行:

    dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 10; i ++) {
        dispatch_async(queue, ^{
            NSLog(@"queue6 -- %d -----%@",i,[NSThread currentThread]);
        });
    }

執(zhí)行結(jié)果:

2018-11-07 09:14:53.988564+0800 09-線程[2145:44288] queue6 -- 0 -----<NSThread: 0x600000268d00>{number = 3, name = (null)}
2018-11-07 09:14:53.988575+0800 09-線程[2145:44289] queue6 -- 3 -----<NSThread: 0x6000002687c0>{number = 6, name = (null)}
2018-11-07 09:14:53.988569+0800 09-線程[2145:44290] queue6 -- 2 -----<NSThread: 0x600000267080>{number = 5, name = (null)}
2018-11-07 09:14:53.988607+0800 09-線程[2145:44287] queue6 -- 1 -----<NSThread: 0x600000268980>{number = 4, name = (null)}
2018-11-07 09:14:53.988889+0800 09-線程[2145:44288] queue6 -- 4 -----<NSThread: 0x600000268d00>{number = 3, name = (null)}
2018-11-07 09:14:53.988926+0800 09-線程[2145:44289] queue6 -- 5 -----<NSThread: 0x6000002687c0>{number = 6, name = (null)}
2018-11-07 09:14:53.989017+0800 09-線程[2145:44314] queue6 -- 6 -----<NSThread: 0x600000267000>{number = 7, name = (null)}
2018-11-07 09:14:53.989041+0800 09-線程[2145:44315] queue6 -- 7 -----<NSThread: 0x604000274080>{number = 8, name = (null)}
2018-11-07 09:14:53.989114+0800 09-線程[2145:44316] queue6 -- 8 -----<NSThread: 0x604000273e40>{number = 10, name = (null)}
2018-11-07 09:14:53.989114+0800 09-線程[2145:44317] queue6 -- 9 -----<NSThread: 0x604000273f40>{number = 9, name = (null)}

異步并行下,開啟了多個線程去同時執(zhí)行任務(wù)

線程死鎖

先來看以下代碼:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"1");
    });
}

這里,viewDidLoad^{ NSLog(@"1") },為兩個任務(wù)AB,首先A在主隊(duì)列,并且在主線程執(zhí)行,這時候主隊(duì)列加入了任務(wù)B,于是主隊(duì)列的順序就是 A執(zhí)行完、執(zhí)行B,我們這里又是用串行sync執(zhí)行,需要block的內(nèi)容執(zhí)行完畢(B執(zhí)行完畢),任務(wù)A才執(zhí)行完畢,所以這里就出現(xiàn)了互相等待的死鎖情況。
這里,我們可以把dispatch_get_main_queue() 換成另外一個隊(duì)列,就不會出現(xiàn)死鎖了

線程鎖

當(dāng)我們使用多線程時,操作同一個任務(wù)的時候,是有可能出現(xiàn)線程不安全的問題:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.money = 200;
    
    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)saveMoney {
    int money = self.money;
    sleep(.2);
    money += 50;
    self.money = money;
    
    NSLog(@"存錢50 - 當(dāng)前金額為:%d , 當(dāng)前線程為 %@",self.money,[NSThread currentThread]);
}

- (void)drawMoney {
    int money = self.money;
    sleep(.2);
    money -= 20;
    self.money = money;
    
    NSLog(@"取錢20 - 當(dāng)前金額為:%d , 當(dāng)前線程為 %@",self.money,[NSThread currentThread]);
}

打印結(jié)果:

2018-11-07 15:11:20.045459+0800 09-線程[4708:212472] 取錢20 - 當(dāng)前金額為:180 , 當(dāng)前線程為 <NSThread: 0x600000276fc0>{number = 4, name = (null)}
2018-11-07 15:11:20.045453+0800 09-線程[4708:212475] 存錢50 - 當(dāng)前金額為:250 , 當(dāng)前線程為 <NSThread: 0x6000002770c0>{number = 3, name = (null)}
2018-11-07 15:11:20.045730+0800 09-線程[4708:212475] 存錢50 - 當(dāng)前金額為:230 , 當(dāng)前線程為 <NSThread: 0x6000002770c0>{number = 3, name = (null)}
2018-11-07 15:11:20.045797+0800 09-線程[4708:212472] 取錢20 - 當(dāng)前金額為:210 , 當(dāng)前線程為 <NSThread: 0x600000276fc0>{number = 4, name = (null)}
2018-11-07 15:11:20.046415+0800 09-線程[4708:212475] 存錢50 - 當(dāng)前金額為:260 , 當(dāng)前線程為 <NSThread: 0x6000002770c0>{number = 3, name = (null)}
2018-11-07 15:11:20.046626+0800 09-線程[4708:212472] 取錢20 - 當(dāng)前金額為:240 , 當(dāng)前線程為 <NSThread: 0x600000276fc0>{number = 4, name = (null)}
2018-11-07 15:11:20.046797+0800 09-線程[4708:212475] 存錢50 - 當(dāng)前金額為:290 , 當(dāng)前線程為 <NSThread: 0x6000002770c0>{number = 3, name = (null)}
2018-11-07 15:11:20.046900+0800 09-線程[4708:212472] 取錢20 - 當(dāng)前金額為:270 , 當(dāng)前線程為 <NSThread: 0x600000276fc0>{number = 4, name = (null)}
2018-11-07 15:11:20.047037+0800 09-線程[4708:212475] 存錢50 - 當(dāng)前金額為:320 , 當(dāng)前線程為 <NSThread: 0x6000002770c0>{number = 3, name = (null)}
2018-11-07 15:11:20.048622+0800 09-線程[4708:212472] 取錢20 - 當(dāng)前金額為:300 , 當(dāng)前線程為 <NSThread: 0x600000276fc0>{number = 4, name = (null)}
2018-11-07 15:11:20.049292+0800 09-線程[4708:212475] 存錢50 - 當(dāng)前金額為:350 , 當(dāng)前線程為 <NSThread: 0x6000002770c0>{number = 3, name = (null)}
2018-11-07 15:11:20.049894+0800 09-線程[4708:212472] 取錢20 - 當(dāng)前金額為:330 , 當(dāng)前線程為 <NSThread: 0x600000276fc0>{number = 4, name = (null)}
2018-11-07 15:11:20.050160+0800 09-線程[4708:212475] 存錢50 - 當(dāng)前金額為:380 , 當(dāng)前線程為 <NSThread: 0x6000002770c0>{number = 3, name = (null)}
2018-11-07 15:11:20.051462+0800 09-線程[4708:212472] 取錢20 - 當(dāng)前金額為:360 , 當(dāng)前線程為 <NSThread: 0x600000276fc0>{number = 4, name = (null)}
2018-11-07 15:11:20.051761+0800 09-線程[4708:212475] 存錢50 - 當(dāng)前金額為:410 , 當(dāng)前線程為 <NSThread: 0x6000002770c0>{number = 3, name = (null)}
2018-11-07 15:11:20.052363+0800 09-線程[4708:212472] 取錢20 - 當(dāng)前金額為:390 , 當(dāng)前線程為 <NSThread: 0x600000276fc0>{number = 4, name = (null)}
2018-11-07 15:11:20.052789+0800 09-線程[4708:212475] 存錢50 - 當(dāng)前金額為:440 , 當(dāng)前線程為 <NSThread: 0x6000002770c0>{number = 3, name = (null)}
2018-11-07 15:11:20.053310+0800 09-線程[4708:212472] 取錢20 - 當(dāng)前金額為:420 , 當(dāng)前線程為 <NSThread: 0x600000276fc0>{number = 4, name = (null)}
2018-11-07 15:11:20.053921+0800 09-線程[4708:212475] 存錢50 - 當(dāng)前金額為:470 , 當(dāng)前線程為 <NSThread: 0x6000002770c0>{number = 3, name = (null)}
2018-11-07 15:11:20.054219+0800 09-線程[4708:212472] 取錢20 - 當(dāng)前金額為:450 , 當(dāng)前線程為 <NSThread: 0x600000276fc0>{number = 4, name = (null)}

照理說,我們進(jìn)行了10次的存錢取錢,最終得到的結(jié)果應(yīng)該是500塊錢,可是這里卻沒有,原因是因?yàn)槲覀冊诖驽X/取錢的時候,是同時進(jìn)行的,假如當(dāng)?shù)谝淮稳〕龅腻Xself.money是200,這時候進(jìn)行了存錢操作,則記錄為250,但是取錢又是同時進(jìn)行的,在存錢操作沒有做完的時候,取錢操作取出的錢也是200,進(jìn)行取錢操作后記錄為180,這時候無論誰把錢賦值給self.money都是錯誤的,所以這里存錢和取錢的操作應(yīng)該是分開進(jìn)行的,于是我們就有了線程鎖的概念。
線程鎖有很多種,包括:

  • OSSpinLock : iOS10之前的線程鎖,現(xiàn)在已經(jīng)不安全了,會出現(xiàn)優(yōu)先級反轉(zhuǎn)的問題 (自旋鎖)
  • os_unfair_lock : iOS10之后替換OSSpinLock
  • pthread_mutex: 跨平臺鎖,可傳入屬性,作為遞歸鎖
  • dispatch_semaphore (信號量): 控制線程的并發(fā)數(shù)量
  • NSConditionLock:線程先后執(zhí)行順序
  • @synchroized :對象鎖,傳入的同一個對象就可以實(shí)現(xiàn)同步,性能較差(封裝pthread_mutex),但是用法最簡單
    …………
    性能排序

線程鎖用法

這里主要講 dispatch_semaphore、 @synchroized、NSConditionLock的用法

dispatch_semaphore

- (void)viewDidLoad {
    [super viewDidLoad];
    // 傳入的5表示控制線程最大的并發(fā)數(shù)量為5
    self.semaphore = dispatch_semaphore_create(5);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    for (int i = 0; i < 20; i++) {
        [[[NSThread alloc] initWithTarget:self selector:@selector(semaphoreTest) object:nil] start];
    }
}
- (void)semaphoreTest {
    // 如果信號量的值 > 0,就讓信號量的值減1,然后繼續(xù)往下執(zhí)行代碼
    // 如果信號量的值 <= 0,就會休眠等待,直到信號量的值變成>0,就讓信號量的值減1,然后繼續(xù)往下執(zhí)行代碼
    dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
    
    sleep(2);
    NSLog(@"test - %@", [NSThread currentThread]);
    
    // 讓信號量的值+1
    dispatch_semaphore_signal(self.semaphore);
}

打印結(jié)果:

2018-11-08 09:42:43.756944+0800 09-線程[1815:57093] test - <NSThread: 0x604000278880>{number = 4, name = (null)}
2018-11-08 09:42:43.756940+0800 09-線程[1815:57094] test - <NSThread: 0x60400026fd40>{number = 5, name = (null)}
2018-11-08 09:42:43.756937+0800 09-線程[1815:57096] test - <NSThread: 0x60400026f880>{number = 7, name = (null)}
2018-11-08 09:42:43.757042+0800 09-線程[1815:57095] test - <NSThread: 0x604000279400>{number = 6, name = (null)}
2018-11-08 09:42:43.757078+0800 09-線程[1815:57092] test - <NSThread: 0x60400026f040>{number = 3, name = (null)}
2018-11-08 09:42:45.763554+0800 09-線程[1815:57097] test - <NSThread: 0x604000270900>{number = 8, name = (null)}
2018-11-08 09:42:45.763560+0800 09-線程[1815:57099] test - <NSThread: 0x604000274000>{number = 10, name = (null)}
2018-11-08 09:42:45.763649+0800 09-線程[1815:57098] test - <NSThread: 0x604000274080>{number = 9, name = (null)}
2018-11-08 09:42:45.763702+0800 09-線程[1815:57100] test - <NSThread: 0x604000276740>{number = 11, name = (null)}
2018-11-08 09:42:45.763807+0800 09-線程[1815:57101] test - <NSThread: 0x604000274c80>{number = 12, name = (null)}
2018-11-08 09:42:47.770115+0800 09-線程[1815:57104] test - <NSThread: 0x60400026d480>{number = 15, name = (null)}
2018-11-08 09:42:47.770243+0800 09-線程[1815:57103] test - <NSThread: 0x604000278b40>{number = 14, name = (null)}
2018-11-08 09:42:47.770122+0800 09-線程[1815:57102] test - <NSThread: 0x60400026d680>{number = 13, name = (null)}
2018-11-08 09:42:47.770250+0800 09-線程[1815:57106] test - <NSThread: 0x604000278ac0>{number = 17, name = (null)}
2018-11-08 09:42:47.770243+0800 09-線程[1815:57105] test - <NSThread: 0x6040002797c0>{number = 16, name = (null)}
2018-11-08 09:42:49.775898+0800 09-線程[1815:57107] test - <NSThread: 0x604000279b40>{number = 18, name = (null)}
2018-11-08 09:42:49.775904+0800 09-線程[1815:57108] test - <NSThread: 0x604000277f80>{number = 19, name = (null)}
2018-11-08 09:42:49.775948+0800 09-線程[1815:57109] test - <NSThread: 0x604000279980>{number = 20, name = (null)}
2018-11-08 09:42:49.776003+0800 09-線程[1815:57111] test - <NSThread: 0x604000278080>{number = 22, name = (null)}
2018-11-08 09:42:49.776007+0800 09-線程[1815:57110] test - <NSThread: 0x604000279a00>{number = 21, name = (null)}

每次相差2秒執(zhí)行5個線程的操作,如果要做成同步鎖的話,傳入的信號量的值為1就好了。
@synchroized

- (void)synchronizedTestTest
{
    @synchronized([self class]) {
        sleep(1);
        NSLog(@"123 - %@",[NSThread currentThread]);
    }
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    for (int i = 0; i < 20; i++) {
        [[[NSThread alloc] initWithTarget:self selector:@selector(synchronizedTestTest) object:nil] start];
    }
}

打印結(jié)果

2018-11-08 09:52:08.104731+0800 09-線程[1990:66615] 123 - <NSThread: 0x60400027e780>{number = 3, name = (null)}
2018-11-08 09:52:09.107712+0800 09-線程[1990:66616] 123 - <NSThread: 0x60400027e140>{number = 4, name = (null)}
2018-11-08 09:52:10.112815+0800 09-線程[1990:66617] 123 - <NSThread: 0x60400027eb00>{number = 5, name = (null)}
2018-11-08 09:52:11.118213+0800 09-線程[1990:66618] 123 - <NSThread: 0x60400027e1c0>{number = 6, name = (null)}
2018-11-08 09:52:12.123081+0800 09-線程[1990:66619] 123 - <NSThread: 0x60400027ea80>{number = 7, name = (null)}
2018-11-08 09:52:13.124789+0800 09-線程[1990:66620] 123 - <NSThread: 0x60400027e840>{number = 8, name = (null)}
2018-11-08 09:52:14.130562+0800 09-線程[1990:66621] 123 - <NSThread: 0x60400027ea40>{number = 9, name = (null)}
2018-11-08 09:52:15.133153+0800 09-線程[1990:66622] 123 - <NSThread: 0x60400027e180>{number = 10, name = (null)}

@synchronized 鎖的對象可以是任何對象,只要在需要的場景使用相同的一個對象作為鎖就可以了

NSConditionLock


- (void)viewDidLoad {
    [super viewDidLoad];
 self.conditionLock = [[NSConditionLock alloc] initWithCondition:1];
    
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [[[NSThread alloc] initWithTarget:self selector:@selector(__one) object:nil] start];
    
    [[[NSThread alloc] initWithTarget:self selector:@selector(__two) object:nil] start];
    
    [[[NSThread alloc] initWithTarget:self selector:@selector(__three) object:nil] start];
}

- (void)__one
{
    [self.conditionLock lock];
    
    NSLog(@"__one");
    sleep(1);
    
    [self.conditionLock unlockWithCondition:2];
}

- (void)__two
{
    [self.conditionLock lockWhenCondition:2];
    
    NSLog(@"__two");
    sleep(1);
    
    [self.conditionLock unlockWithCondition:3];
}

- (void)__three
{
    [self.conditionLock lockWhenCondition:3];
    
    NSLog(@"__three");
    
    [self.conditionLock unlock];
}

執(zhí)行結(jié)果:

2018-11-08 09:58:50.013405+0800 09-線程[2114:72695] __one
2018-11-08 09:58:51.017919+0800 09-線程[2114:72696] __two
2018-11-08 09:58:52.023380+0800 09-線程[2114:72697] __three

會依次執(zhí)行one、two、three,Condition的默認(rèn)條件是0

Atomic

atomic (原子性),在屬性賦值的時候系統(tǒng)內(nèi)部會封裝一層spinlock進(jìn)行加鎖解鎖操作
nonatomic (非原子性),直接賦值

dispatch_barrier_sync

線程安全中,其實(shí)只要保證單寫多讀就可以,用dispatch_barrier_sync就可以實(shí)現(xiàn),在dispatch_barrier_sync執(zhí)行寫的操作,如圖


注: 此函數(shù)需要在創(chuàng)建的并行隊(duì)列執(zhí)行

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容