日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iOS开发-多线程开发之线程安全篇

發布時間:2025/4/9 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS开发-多线程开发之线程安全篇 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:一塊資源可能會被多個線程共享,也就是多個線程可能會訪問同一塊資源,比如多個線程訪問同一個對象、同一個變量、同一個文件和同一個方法等。因此當多個線程訪問同一塊資源時,很容易會發生數據錯誤及數據不安全等問題。因此要避免這些問題,我們需要使用“線程鎖”來實現。

?

本文主要論述IOS創建鎖的方法總結,如果大家對多線程編程技術這一塊不熟悉,我建議你們先去看我的另一篇文章”iOS開發-多線程編程技術(Thread、Cocoa operations、GCD)“

?

一、使用關鍵字

1)@synchronized(互斥鎖)

優點:使用@synchronized關鍵字可以很方便地創建鎖對象,而且不用顯式的創建鎖對象。

缺點:會隱式添加一個異常處理來保護代碼,該異常處理會在異常拋出的時候自動釋放互斥鎖。而這種隱式的異常處理會帶來系統的額外開銷,為優化資源,你可以使用鎖對象。

二、Object-C”語言

1)NSLock(互斥鎖)

2)NSRecursiveLock(遞歸鎖)

條件鎖,遞歸或循環方法時使用此方法實現鎖,可避免死鎖等問題。

3)NSConditionLock(條件鎖)

使用此方法可以指定,只有滿足條件的時候才可以解鎖。

4)NSDistributedLock(分布式鎖)

在IOS中不需要用到,也沒有這個方法,因此本文不作介紹,這里寫出來只是想讓大家知道有這個鎖存在。

如果想要學習NSDistributedLock的話,你可以創建MAC OS的項目自己演練,方法請自行Google,謝謝。

三、C語言

1)pthread_mutex_t(互斥鎖)

2)GCD-信號量(“互斥鎖”)

3)pthread_cond_t(條件鎖)

?

線程安全 —— 鎖

一、使用關鍵字

1)@synchronized

// 實例類person Person *person = [[Person alloc] init];// 線程A dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{@synchronized(person) {[person personA];[NSThread sleepForTimeInterval:3]; // 線程休眠3秒} });// 線程B dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{@synchronized(person) {[person personB];} });

關鍵字@synchronized的使用,鎖定的對象為鎖的唯一標識,只有標識相同時,才滿足互斥。如果線程B鎖對象person改為self或其它標識,那么線程B將不會被阻塞。你是否看到@synchronized(self) ,也是對的。它可以鎖任何對象,描述為@synchronized(anObj)。

?

二、Object-C語言

1)使用NSLock實現鎖

// 實例類person Person *person = [[Person alloc] init]; // 創建鎖 NSLock *myLock = [[NSLock alloc] init];// 線程A dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{[myLock lock];[person personA];[NSThread sleepForTimeInterval:5];[myLock unlock]; });// 線程B dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{[myLock lock];[person personB];[myLock unlock]; });?

程序運行結果:線程B會等待線程A解鎖后,才會去執行線程B。如果線程Blockunlock方法去掉之后,則線程B不會被阻塞,這個和synchronized的一樣,需要使用同樣的鎖對象才會互斥。

NSLock類還提供tryLock方法,意思是嘗試鎖定,當鎖定失敗時,不會阻塞進程,而是會返回NO。你也可以使用lockBeforeDate:方法,意思是在指定時間之前嘗試鎖定,如果在指定時間前都不能鎖定,也是會返回NO。

注意:鎖定(lock)和解鎖(unLock)必須配對使用

?

2)使用NSRecursiveLock類實現鎖?

// 實例類person Person *person = [[Person alloc] init]; // 創建鎖對象 NSRecursiveLock *theLock = [[NSRecursiveLock alloc] init];// 創建遞歸方法 static void (^testCode)(int); testCode = ^(int value) {[theLock tryLock];if (value > 0){[person personA];[NSThread sleepForTimeInterval:1];testCode(value - 1);}[theLock unlock]; };//線程A dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{testCode(5); });//線程B dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{[theLock lock];[person personB];[theLock unlock]; });

如果我們把NSRecursiveLock類換成NSLock類,那么程序就會死鎖。因為在此例子中,遞歸方法會造成鎖被多次鎖定(Lock),所以自己也被阻塞了。而使用NSRecursiveLock類,則可以避免這個問題。

?

3)使用NSConditionLock(條件鎖)類實現鎖:

使用此方法可以創建一個指定開鎖的條件,只有滿足條件,才能開鎖。

// 實例類person Person *person = [[Person alloc] init]; // 創建條件鎖 NSConditionLock *conditionLock = [[NSConditionLock alloc] init];// 線程A dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{[conditionLock lock];[person personA];[NSThread sleepForTimeInterval:5];[conditionLock unlockWithCondition:10]; });// 線程B dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{[conditionLock lockWhenCondition:10];[person personB];[conditionLock unlock]; });

線程A使用的是lock方法,因此會直接進行鎖定,并且指定了只有滿足10的情況下,才能成功解鎖。

unlockWithCondition:方法,創建條件鎖,參數傳入“整型”。lockWhenCondition:方法,則為解鎖,也是傳入一個“整型”的參數。

?

三、C語言

1)使用pthread_mutex_t實現鎖

注意:必須在頭文件導入:#import <pthread.h>

// 實例類person Person *person = [[Person alloc] init];// 創建鎖對象 __block pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL);// 線程A dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{pthread_mutex_lock(&mutex);[person personA];[NSThread sleepForTimeInterval:5];pthread_mutex_unlock(&mutex); });// 線程B dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{pthread_mutex_lock(&mutex);[person personB];pthread_mutex_unlock(&mutex); });

實現效果和上例的相一致

??

2)使用GCD實現(信號量)

GCD提供一種信號的機制,使用它我們可以創建“鎖”(信號量和鎖是有區別的,具體請自行百度)。

// 實例類person Person *person = [[Person alloc] init];// 創建并設置信量 dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);// 線程A dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);[person personA];[NSThread sleepForTimeInterval:5];dispatch_semaphore_signal(semaphore); });// 線程B dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);[person personB];dispatch_semaphore_signal(semaphore); });

效果也是和上例介紹的相一致。

我在這里解釋一下代碼。dispatch_semaphore_wait方法是把信號量加1,dispatch_semaphore_signal是把信號量減1。

我們把信號量當作是一個計數器,當計數器是一個非負整數時,所有通過它的線程都應該把這個整數減1。如果計數器大于0,那么則允許訪問,并把計數器減1。如果為0,則訪問被禁止,所有通過它的線程都處于等待的狀態。

?

3)使用POSIX(條件鎖)創建鎖

// 實例類person Person *person = [[Person alloc] init];// 創建互斥鎖 __block pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL); // 創建條件鎖 __block pthread_cond_t cond; pthread_cond_init(&cond, NULL);// 線程A dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{pthread_mutex_lock(&mutex);pthread_cond_wait(&cond, &mutex);[person personA];pthread_mutex_unlock(&mutex); });// 線程B dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{pthread_mutex_lock(&mutex);[person personB];[NSThread sleepForTimeInterval:5];pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex); });

效果:程序會首先調用線程B,在5秒后再調用線程A。因為在線程A中創建了等待條件鎖,線程B有激活鎖,只有當線程B執行完后會激活線程A。

pthread_cond_wait方法為等待條件鎖。

pthread_cond_signal方法為激動一個相同條件的條件鎖。

?

?

簡單總結:

一般來說,如果項目不大,我們都會偷點懶,直接使用關鍵字@synchronized建立鎖,懶人方法。其次可以使用蘋果提供的OC方法,最后才會去使用C去建立鎖。

?

?

?

?

本文參考文章:

iOS多線程開發(四)---線程同步

Objective-C中不同方式實現鎖(一)

信號量與互斥鎖

?

?

?


博文作者:GarveyCalvin

博文出處:http://www.cnblogs.com/GarveyCalvin/

本文版權歸作者和博客園共有,歡迎轉載,但須保留此段聲明,并給出原文鏈接,謝謝合作!

?

轉載于:https://www.cnblogs.com/GarveyCalvin/p/4212611.html

總結

以上是生活随笔為你收集整理的iOS开发-多线程开发之线程安全篇的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。