進(jìn)程 & 線程
- 提到線程捌朴,那就不得不提CPU吴攒,現(xiàn)代的CPU有一個(gè)很重要的特性,就是時(shí)間片男旗,每一個(gè)獲得CPU的任務(wù)只能運(yùn)行一個(gè)時(shí)間片規(guī)定的時(shí)間舶斧。
- 其實(shí)線程對操作系統(tǒng)來說就是一段代碼以及運(yùn)行時(shí)數(shù)據(jù)卧波。操作系統(tǒng)會(huì)為每個(gè)線程保存相關(guān)的數(shù)據(jù)于游,當(dāng)接收到來自CPU的時(shí)間片中斷事件時(shí)涛酗,就會(huì)按一定規(guī)則從這些線程中選擇一個(gè),恢復(fù)它的運(yùn)行時(shí)數(shù)據(jù)誓焦,這樣CPU就可以繼續(xù)執(zhí)行這個(gè)線程了蠕嫁。
- 也就是其實(shí)就單核CUP而言冰寻,并沒有辦法實(shí)現(xiàn)真正意義上的并發(fā)執(zhí)行觉阅,只是CPU快速地在多條線程之間調(diào)度,CPU調(diào)度線程的時(shí)間足夠快嗜闻,就造成了多線程并發(fā)執(zhí)行的假象蜕依。并且就單核CPU而言多線程可以解決線程阻塞的問題,但是其本身運(yùn)行效率并沒有提高琉雳,多CPU的并行運(yùn)算才真正解決了運(yùn)行效率問題样眠。
- 系統(tǒng)中正在運(yùn)行的每一個(gè)應(yīng)用程序都是一個(gè)進(jìn)程,每個(gè)進(jìn)程系統(tǒng)都會(huì)分配給它獨(dú)立的內(nèi)存運(yùn)行翠肘。也就是說檐束,在iOS系統(tǒng)中中,每一個(gè)應(yīng)用都是一個(gè)進(jìn)程束倍。
- 一個(gè)進(jìn)程的所有任務(wù)都在線程中進(jìn)行被丧,因此每個(gè)進(jìn)程至少要有一個(gè)線程,也就是主線程绪妹。那多線程其實(shí)就是一個(gè)進(jìn)程開啟多條線程甥桂,讓所有任務(wù)并發(fā)執(zhí)行。
- 多線程在一定意義上實(shí)現(xiàn)了進(jìn)程內(nèi)的資源共享邮旷,以及效率的提升黄选。同時(shí),在一定程度上相對獨(dú)立廊移,它是程序執(zhí)行流的最小單元糕簿,是進(jìn)程中的一個(gè)實(shí)體,是執(zhí)行程序最基本的單元狡孔,有自己棧和寄存器
同步異步 & 串行并行
同步與異步的區(qū)別:具不具備開線程的能力
串行與并行:可不可以同時(shí)執(zhí)行多個(gè)任務(wù),異步是多個(gè)任務(wù)并行的前提條件
舉個(gè)栗子 & 同步異步
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)}
異步
下蜂嗽,開啟了一個(gè)子線程number 3
去執(zhí)行任務(wù)
舉個(gè)栗子 & 串行并行
異步串行:
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)}
異步并行下苗膝,開啟了多個(gè)線程去同時(shí)執(zhí)行任務(wù)
線程死鎖
先來看以下代碼:
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"1");
});
}
這里,viewDidLoad
和^{ NSLog(@"1") }
植旧,為兩個(gè)任務(wù)A
和B
辱揭,首先A
在主隊(duì)列,并且在主線程執(zhí)行病附,這時(shí)候主隊(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()
換成另外一個(gè)隊(duì)列,就不會(huì)出現(xiàn)死鎖了
線程鎖
當(dāng)我們使用多線程時(shí)尉姨,操作同一個(gè)任務(wù)的時(shí)候庵朝,是有可能出現(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/取錢的時(shí)候覆致,是同時(shí)進(jìn)行的侄旬,假如當(dāng)?shù)谝淮稳〕龅腻Xself.money
是200,這時(shí)候進(jìn)行了存錢操作篷朵,則記錄為250勾怒,但是取錢又是同時(shí)進(jìn)行的,在存錢操作沒有做完的時(shí)候声旺,取錢操作取出的錢也是200笔链,進(jìn)行取錢操作后記錄為180
,這時(shí)候無論誰把錢賦值給self.money
都是錯(cuò)誤的腮猖,所以這里存錢和取錢的操作應(yīng)該是分開進(jìn)行的鉴扫,于是我們就有了線程鎖的概念。
線程鎖有很多種澈缺,包括:
- OSSpinLock : iOS10之前的線程鎖坪创,現(xiàn)在已經(jīng)不安全了,會(huì)出現(xiàn)優(yōu)先級反轉(zhuǎn)的問題 (自旋鎖)
- os_unfair_lock : iOS10之后替換OSSpinLock
- pthread_mutex: 跨平臺(tái)鎖姐赡,可傳入屬性莱预,作為遞歸鎖
- dispatch_semaphore (信號(hào)量): 控制線程的并發(fā)數(shù)量
- NSConditionLock:線程先后執(zhí)行順序
-
@synchroized :對象鎖,傳入的同一個(gè)對象就可以實(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 {
// 如果信號(hào)量的值 > 0危喉,就讓信號(hào)量的值減1,然后繼續(xù)往下執(zhí)行代碼
// 如果信號(hào)量的值 <= 0州疾,就會(huì)休眠等待辜限,直到信號(hào)量的值變成>0,就讓信號(hào)量的值減1严蓖,然后繼續(xù)往下執(zhí)行代碼
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
sleep(2);
NSLog(@"test - %@", [NSThread currentThread]);
// 讓信號(hào)量的值+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個(gè)線程的操作薄嫡,如果要做成同步鎖的話氧急,傳入的信號(hào)量的值為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 鎖的對象可以是任何對象岂座,只要在需要的場景使用相同的一個(gè)對象作為鎖就可以了
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
會(huì)依次執(zhí)行one
态蒂、two
、three
费什,Condition的默認(rèn)條件是0
Atomic
atomic (原子性)钾恢,在屬性賦值的時(shí)候系統(tǒng)內(nèi)部會(huì)封裝一層spinlock
進(jìn)行加鎖解鎖操作
nonatomic (非原子性),直接賦值
dispatch_barrier_sync
線程安全中鸳址,其實(shí)只要保證單寫多讀
就可以瘩蚪,用dispatch_barrier_sync
就可以實(shí)現(xiàn),在dispatch_barrier_sync
執(zhí)行寫的操作稿黍,如圖
注: 此函數(shù)需要在創(chuàng)建的并行隊(duì)列執(zhí)行