進(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ù)A和B,首先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í)行
