1. 程式人生 > >iOS多執行緒-各種執行緒鎖的簡單介紹

iOS多執行緒-各種執行緒鎖的簡單介紹

執行緒安全是怎麼產生的

常見比如執行緒內操作了一個執行緒外的非執行緒安全變數,這個時候一定要考慮執行緒安全和同步。

- (void)getIamgeName:(NSMutableArray *)imageNames{//假如每個進來的都是一個執行緒
    /*1.imageNames是執行緒外的變數,這個時候就需要考慮執行緒安全,
    因為,假如我們當前imageNames的個數是1,執行緒A和B同時進來發現個數是大於0的,
    都會去執行remove操作,結果肯定會有一個執行緒崩潰掉。
    */
    /*2.NSMutableArray *array = [[NSMutableArray alloc]initWithArray:imageNames];
    這裡如果新生成一個array,下面也把imageNames換成array就不需要考慮執行緒安全,
    但是這樣array.count判斷永遠大於0,也就是永遠等於imageNames.count
     */
NSString *imageName; if (imageNames.count>0) { imageName = [imageNames lastObject]; [imageNames removeObject:imageName]; } }

下面是鎖的同步方案

鎖的概念

鎖是最常用的同步工具。一段程式碼段在同一個時間只能允許被一個執行緒訪問,比如一個執行緒A進入加鎖程式碼之後由於已經加鎖,另一個執行緒B就無法訪問,只有等待前一個執行緒A執行完加鎖程式碼後解鎖,B執行緒才能訪問加鎖程式碼。
不要將過多的其他操作程式碼放到裡面,否則一個執行緒執行的時候另一個執行緒就一直在等待,就無法發揮多執行緒的作用了。

NSLock

在Cocoa程式中NSLock中實現了一個簡單的互斥鎖,實現了NSLocking protocol。
lock,加鎖
unlock,解鎖
tryLock,嘗試加鎖,如果失敗了,並不會阻塞執行緒,只是立即返回
NOlockBeforeDate:,在指定的date之前暫時阻塞執行緒(如果沒有獲取鎖的話),如果到期還沒有獲取鎖,則執行緒被喚醒,函式立即返回NO
使用tryLock並不能成功加鎖,如果獲取鎖失敗就不會執行加鎖程式碼了。

- (void)getIamgeName:(NSMutableArray *)imageNames{
    NSString *imageName;
    [lock
lock]; if (imageNames.count>0) { imageName = [imageNames lastObject]; [imageNames removeObject:imageName]; } [lock unlock]; }

@synchronized程式碼塊

每個iOS開發最早接觸的執行緒鎖就是@synchronized,程式碼簡單。

- (void)getIamgeName:(int)index{
    NSString *imageName;
    @synchronized(self) {
        if (imageNames.count>0) {
            imageName = [imageNames lastObject];
            [imageNames removeObject:imageName];
        }
    }
}

條件訊號量dispatch_semaphore_t

dispatch_semaphore_tGCD中訊號量,也可以解決資源搶佔問題,支援訊號通知和訊號等待。每當傳送一個訊號通知,則訊號量+1;每當傳送一個等待訊號時訊號量-1,;如果訊號量為0則訊號會處於等待狀態,直到訊號量大於0開始執行。

#import "MYDispatchSemaphoreViewController.h"

@interface MYDispatchSemaphoreViewController ()
{
    dispatch_semaphore_t semaphore;
}
@end

@implementation MYDispatchSemaphoreViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    semaphore = dispatch_semaphore_create(1);
    /**
     *  建立一個訊號量為1的訊號
     *
     */
}

- (void)getIamgeName:(NSMutableArray *)imageNames{
    NSString *imageName;
    /**
     *  semaphore:等待訊號
     DISPATCH_TIME_FOREVER:等待時間
     wait之後訊號量-1,為0
     */
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    if (imageNames.count>0) {
        imageName = [imageNames lastObject];
        [imageNames removeObject:imageName];
    }
    /**
     *  傳送一個訊號通知,這時候訊號量+1,為1
     */
    dispatch_semaphore_signal(semaphore);
}

@end

條件鎖NSCondition

NSCondition同樣實現了NSLocking協議,所以它和NSLock一樣,也有NSLocking協議的lock和unlock方法,可以當做NSLock來使用解決執行緒同步問題,用法完全一樣。

- (void)getIamgeName:(NSMutableArray *)imageNames{
    NSString *imageName;
    [lock lock];
    if (imageNames.count>0) {
        imageName = [imageNames lastObject];
        [imageNames removeObject:imageName];
    }
    [lock unlock];
}

同時,NSCondition提供更高階的用法。wait和signal,和條件訊號量類似。
比如我們要監聽imageNames陣列的個數,當imageNames的個數大於0的時候就執行清空操作。思路是這樣的,當imageNames個數大於0時執行清空操作,否則,wait等待執行清空操作。當imageNames個數增加的時候發生signal訊號,讓等待的執行緒喚醒繼續執行。
NSCondition和NSLock、@synchronized等是不同的是,NSCondition可以給每個執行緒分別加鎖,加鎖後不影響其他執行緒進入臨界區。這是非常強大。
但是正是因為這種分別加鎖的方式,NSCondition使用wait並使用加鎖後並不能真正的解決資源的競爭。比如我們有個需求:不能讓m<0。假設當前m=0,執行緒A要判斷到m>0為假,執行等待;執行緒B執行了m=1操作,並喚醒執行緒A執行m-1操作的同時執行緒C判斷到m>0,因為他們在不同的執行緒鎖裡面,同樣判斷為真也執行了m-1,這個時候執行緒A和執行緒C都會執行m-1,但是m=1,結果就會造成m=-1.
當我用陣列做刪除試驗時,做增刪操作並不是每次都會出現,大概3-4次後會出現。單純的使用lock、unlock是沒有問題的。

- (void)getIamgeName:(NSMutableArray *)imageNames{
    NSString *imageName;
    [lock lock];    //加鎖
    static int m = 0;
    static int n = 0;
    static int p = 0;
    NSLog(@"removeObjectBegin count: %ld\n",imageNames.count);

    if (imageNames.count>0) {
        imageName = [imageNames lastObject];
        [imageNames removeObjectAtIndex:0];
        m++;
        NSLog(@"執行了%d次刪除操作",m);
    } else {
        p++;
        NSLog(@"執行了%d次等待",p);
        [lock wait];    //等待
        imageName = [imageNames lastObject];
        [imageNames removeObjectAtIndex:0];
        /**
         *  有時候點選取出圖片會崩潰
         */
        n++;
        NSLog(@"執行了%d次繼續操作",n);
    }

    NSLog(@"removeObject count: %ld\n",imageNames.count);
    [lock unlock];     //解鎖
}
- (void)createImageName:(NSMutableArray *)imageNames{
    [lock lock];
    static int m = 0;
    [imageNames addObject:@"0"];
    m++;
    NSLog(@"添加了%d次",m);
    [lock signal];  //喚醒隨機一個執行緒取消等待繼續執行

//        [lock broadcast];   //喚醒所有執行緒取消等待繼續執行
    NSLog(@"createImageName count: %ld\n",imageNames.count);
    [lock unlock];
}

#pragma mark - 多執行緒取出圖片後刪除
- (void)getImageNameWithMultiThread{
    [lock broadcast];
    NSMutableArray *imageNames = [[NSMutableArray alloc]init];
    dispatch_group_t dispatchGroup = dispatch_group_create();
    __block double then, now;
    then = CFAbsoluteTimeGetCurrent();
    for (int i=0; i<10; i++) {
        dispatch_group_async(dispatchGroup, self.synchronizationQueue, ^(){
            [self getIamgeName:imageNames];
        });
        dispatch_group_async(dispatchGroup, self.synchronizationQueue, ^(){
            [self createImageName:imageNames];
        });
    }
    dispatch_group_notify(dispatchGroup, self.synchronizationQueue, ^(){
        now = CFAbsoluteTimeGetCurrent();
        printf("thread_lock: %f sec\nimageNames count: %ld\n", now-then,imageNames.count);
    });

}

條件鎖NSConditionLock

也有人說這是個互斥鎖
NSConditionLock同樣實現了NSLocking協議,試驗過程中發現效能很低。

- (void)getIamgeName:(NSMutableArray *)imageNames{
    NSString *imageName;
    [lock lock];
    if (imageNames.count>0) {
        imageName = [imageNames lastObject];
        [imageNames removeObject:imageName];
    }
    [lock unlock];
}

NSConditionLock也可以像NSCondition一樣做多執行緒之間的任務等待呼叫,而且是執行緒安全的。

- (void)getIamgeName:(NSMutableArray *)imageNames{
    NSString *imageName;
    [lock lockWhenCondition:1];    //加鎖
    if (imageNames.count>0) {
        imageName = [imageNames lastObject];
        [imageNames removeObjectAtIndex:0];
    }
    [lock unlockWithCondition:0];     //解鎖
}
- (void)createImageName:(NSMutableArray *)imageNames{
    [lock lockWhenCondition:0];
    [imageNames addObject:@"0"];
    [lock unlockWithCondition:1];
}

#pragma mark - 多執行緒取出圖片後刪除
- (void)getImageNameWithMultiThread{
    NSMutableArray *imageNames = [[NSMutableArray alloc]init];
    dispatch_group_t dispatchGroup = dispatch_group_create();
    __block double then, now;
    then = CFAbsoluteTimeGetCurrent();
    for (int i=0; i<10000; i++) {
        dispatch_group_async(dispatchGroup, self.synchronizationQueue, ^(){
            [self getIamgeName:imageNames];
        });
        dispatch_group_async(dispatchGroup, self.synchronizationQueue, ^(){
            [self createImageName:imageNames];
        });
    }
    dispatch_group_notify(dispatchGroup, self.synchronizationQueue, ^(){
        now = CFAbsoluteTimeGetCurrent();
        printf("thread_lock: %f sec\nimageNames count: %ld\n", now-then,imageNames.count);
    });
}

遞迴鎖NSRecursiveLock

有時候“加鎖程式碼”中存在遞迴呼叫,遞迴開始前加鎖,遞迴呼叫開始後會重複執行此方法以至於反覆執行加鎖程式碼最終造成死鎖,這個時候可以使用遞迴鎖來解決。使用遞迴鎖可以在一個執行緒中反覆獲取鎖而不造成死鎖,這個過程中會記錄獲取鎖和釋放鎖的次數,只有最後兩者平衡鎖才被最終釋放。

- (void)getIamgeName:(NSMutableArray *)imageNames{
    NSString *imageName;
    [lock lock];
    if (imageNames.count>0) {
        imageName = [imageNames firstObject];
        [imageNames removeObjectAtIndex:0];
        [self getIamgeName:imageNames];
    }
    [lock unlock];
}
- (void)getImageNameWithMultiThread{
    NSMutableArray *imageNames = [NSMutableArray new];
    int count = 1024*10;
    for (int i=0; i<count; i++) {
        [imageNames addObject:[NSString stringWithFormat:@"%d",i]];
    }
    dispatch_group_t dispatchGroup = dispatch_group_create();
    __block double then, now;
    then = CFAbsoluteTimeGetCurrent();
    dispatch_group_async(dispatchGroup, self.synchronizationQueue, ^(){
        [self getIamgeName:imageNames];
    });
    dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){
        now = CFAbsoluteTimeGetCurrent();
        printf("thread_lock: %f sec\nimageNames count: %ld\n", now-then,imageNames.count);
    });

}

NSDistributedLock

NSDistributedLock是MAC開發中的跨程序的分散式鎖,底層是用檔案系統實現的互斥鎖。NSDistributedLock沒有實現NSLocking協議,所以沒有lock方法,取而代之的是非阻塞的tryLock方法。

NSDistributedLock *lock = [[NSDistributedLock alloc] initWithPath:@"/Users/mac/Desktop/lock.lock"];
    while (![lock tryLock])
    {
        sleep(1);
    }

    //do something
    [lock unlock];

當執行到do something時程式退出,程式再次啟動之後tryLock就再也不能成功了,陷入死鎖狀態.其他應用也不能訪問受保護的共享資源。在這種情況下,你可以使用breadLock方法來打破現存的鎖以便你可以獲取它。但是通常應該避免打破鎖,除非你確定擁有程序已經死亡並不可能再釋放該鎖。
因為是MAC下的執行緒鎖,所以demo裡面沒有,這裡也不做過多關注。

互斥鎖POSIX

POSIX和dispatch_semaphore_t很像,但是完全不同。POSIX是Unix/Linux平臺上提供的一套條件互斥鎖的API。
新建一個簡單的POSIX互斥鎖,引入標頭檔案#import <pthread.h>宣告並初始化一個pthread_mutex_t的結構。使用pthread_mutex_lock和pthread_mutex_unlock函式。呼叫pthread_mutex_destroy來釋放該鎖的資料結構。

#import <pthread.h>
@interface MYPOSIXViewController ()
{
    pthread_mutex_t mutex;  //宣告pthread_mutex_t的結構
}
@end

@implementation MYPOSIXViewController
- (void)dealloc{
    pthread_mutex_destroy(&mutex);  //釋放該鎖的資料結構
}
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    pthread_mutex_init(&mutex, NULL);
    /**
     *  初始化
     *
     */
}

- (void)getIamgeName:(NSMutableArray *)imageNames{
    NSString *imageName;
    /**
     *  加鎖
     */
    pthread_mutex_lock(&mutex);
    if (imageNames.count>0) {
        imageName = [imageNames firstObject];
        [imageNames removeObjectAtIndex:0];
    }
    /**
     *  解鎖
     */
    pthread_mutex_unlock(&mutex);
}

POSIX還可以建立條件鎖,提供了和NSCondition一樣的條件控制,初始化互斥鎖同時使用pthread_cond_init來初始化條件資料結構,

    // 初始化
    int pthread_cond_init (pthread_cond_t *cond, pthread_condattr_t *attr);

    // 等待(會阻塞)
    int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mut);

    // 定時等待
    int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mut, const struct timespec *abstime);

    // 喚醒
    int pthread_cond_signal (pthread_cond_t *cond);

    // 廣播喚醒
    int pthread_cond_broadcast (pthread_cond_t *cond);

    // 銷燬
    int pthread_cond_destroy (pthread_cond_t *cond);

POSIX還提供了很多函式,有一套完整的API,包含Pthreads執行緒的建立控制等等,非常底層,可以手動處理執行緒的各個狀態的轉換即管理生命週期,甚至可以實現一套自己的多執行緒,感興趣的可以繼續深入瞭解。推薦一篇詳細文章,但不是基於iOS的,是基於Linux的,但是介紹的非常詳細 Linux 執行緒鎖詳解

自旋鎖OSSpinLock

首先要提的是OSSpinLock已經出現了BUG,導致並不能完全保證是執行緒安全的。

新版 iOS 中,系統維護了 5 個不同的執行緒優先順序/QoS: background,utility,default,user-initiated,user-interactive。高優先順序執行緒始終會在低優先順序執行緒前執行,一個執行緒不會受到比它更低優先順序執行緒的干擾。這種執行緒排程演算法會產生潛在的優先順序反轉問題,從而破壞了 spin lock。
具體來說,如果一個低優先順序的執行緒獲得鎖並訪問共享資源,這時一個高優先順序的執行緒也嘗試獲得這個鎖,它會處於 spin lock 的忙等狀態從而佔用大量 CPU。此時低優先順序執行緒無法與高優先順序執行緒爭奪 CPU 時間,從而導致任務遲遲完不成、無法釋放 lock。這並不只是理論上的問題,libobjc 已經遇到了很多次這個問題了,於是蘋果的工程師停用了 OSSpinLock。
蘋果工程師 Greg Parker 提到,對於這個問題,一種解決方案是用 truly unbounded backoff 演算法,這能避免 livelock 問題,但如果系統負載高時,它仍有可能將高優先順序的執行緒阻塞數十秒之久;另一種方案是使用 handoff lock 演算法,這也是 libobjc 目前正在使用的。鎖的持有者會把執行緒 ID 儲存到鎖內部,鎖的等待者會臨時貢獻出它的優先順序來避免優先順序反轉的問題。理論上這種模式會在比較複雜的多鎖條件下產生問題,但實踐上目前還一切都好。
OSSpinLock 自旋鎖,效能最高的鎖。原理很簡單,就是一直 do while 忙等。它的缺點是當等待時會消耗大量 CPU 資源,所以它不適用於較長時間的任務。對於記憶體快取的存取來說,它非常合適。
-摘自ibireme

所以說不建議再繼續使用,不過可以拿來玩耍一下,匯入標頭檔案#import <libkern/OSAtomic.h>

#import <libkern/OSAtomic.h>
@interface MYOSSpinLockViewController ()
{
    OSSpinLock spinlock;  //宣告pthread_mutex_t的結構
}
@end

@implementation MYOSSpinLockViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    spinlock = OS_SPINLOCK_INIT;
    /**
     *  初始化
     *
     */
}

- (void)getIamgeName:(NSMutableArray *)imageNames{
    NSString *imageName;
    /**
     *  加鎖
     */
    OSSpinLockLock(&spinlock);
    if (imageNames.count>0) {
        imageName = [imageNames firstObject];
        [imageNames removeObjectAtIndex:0];
    }
    /**
     *  解鎖
     */
    OSSpinLockUnlock(&spinlock);
}
@end

OSSpinLock的效能真的很卓越,可惜啦

GCD執行緒阻斷dispatch_barrier_async/dispatch_barrier_sync

dispatch_barrier_async/dispatch_barrier_sync在一定的基礎上也可以做執行緒同步,會線上程佇列中打斷其他執行緒執行當前任務,也就是說只有用在併發的執行緒佇列中才會有效,因為序列佇列本來就是一個一個的執行的,你打斷執行一個和插入一個是一樣的效果。兩個的區別是是否等待任務執行完成。

注意:如果在當前執行緒呼叫dispatch_barrier_sync打斷會發生死鎖。

@interface MYdispatch_barrier_syncViewController ()
{
        __block double then, now;
}
@end

@implementation MYdispatch_barrier_syncViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}
- (void)getIamgeName:(NSMutableArray *)imageNames{
    NSString *imageName;
    if (imageNames.count>0) {
        imageName = [imageNames firstObject];
        [imageNames removeObjectAtIndex:0];
    }else{
        now = CFAbsoluteTimeGetCurrent();
        printf("thread_lock: %f sec\nimageNames count: %ld\n", now-then,imageNames.count);
    }
}

- (void)getImageNameWithMultiThread{
    NSMutableArray *imageNames = [NSMutableArray new];
    int count = 1024*11;
    for (int i=0; i<count; i++) {
        [imageNames addObject:[NSString stringWithFormat:@"%d",i]];
    }
    then = CFAbsoluteTimeGetCurrent();
    for (int i=0; i<count+1; i++) {
        //100來測試鎖有沒有正確的執行
        dispatch_barrier_async(self.synchronizationQueue, ^{
             [self getIamgeName:imageNames];
        });
    }
}

總結

@synchronized:適用執行緒不多,任務量不大的多執行緒加鎖
NSLock:其實NSLock並沒有想象中的那麼差,不知道大家為什麼不推薦使用
dispatch_semaphore_t:使用訊號來做加鎖,效能提升顯著
NSCondition:使用其做多執行緒之間的通訊呼叫不是執行緒安全的
NSConditionLock:單純加鎖效能非常低,比NSLock低很多,但是可以用來做多執行緒處理不同任務的通訊呼叫
NSRecursiveLock:遞迴鎖的效能出奇的高,但是隻能作為遞迴使用,所以限制了使用場景
NSDistributedLock:因為是MAC開發的,就不討論了
POSIX(pthread_mutex):底層的api,複雜的多執行緒處理建議使用,並且可以封裝自己的多執行緒
OSSpinLock:效能也非常高,可惜出現了執行緒問題
dispatch_barrier_async/dispatch_barrier_sync:測試中發現dispatch_barrier_sync比dispatch_barrier_async效能要高,真是大出意外

下面是基準測試
模擬器環境:i5 2.6GH+8G 記憶體,xcode 7.2.1 (7C1002)+iPhone6SP(9.2)


多執行緒鎖刪除陣列效能測試(模擬器).png

真機環境:xcode 7.2.1 (7C1002)+iPhone6(國行)


多執行緒鎖刪除陣列效能測試(iPhone6真機).png

通過測試發現模擬器和真機的區別還是很大的,模擬器上明顯的階梯感,真機就沒有,模擬器上NSConditionLock的效能非常差,我沒有把它的引數加在表格上,不然其他的就看不到了。不過真機上面效能還好。

這些效能測試只是一個參考,沒必要非要去在意這些,畢竟前端的程式設計一般執行緒要求沒那麼高,可以從其他的地方優化。執行緒安全中注意避坑,另外選擇自己喜歡的方式,這樣你可以研究的更深入,使用的更熟練。

另外,demo中我把邏輯拿了出來,算是一個小小的MVVM框架或者MVVCC框架吧
demo在最上方。

2016.6.30更新

有網友提醒我有些鎖在資源競爭激烈和不激烈的情況下效能有差別,於是我修改了原始碼,將原來的開闢大量執行緒邏輯改為開闢3個執行緒,程式碼已更新github,老程式碼在標籤1.0的位置,有興趣可以看下。


多執行緒鎖刪除陣列效能測試(iPhone6真機)2.png

根據新的測試結果,dispatch_barrier_async、dispatch_semaphore_t 、OSSpinLock,三種鎖在資源競爭程度不同下表現比較明顯。

另外再次宣告:測試結果僅僅代表一個參考,因為各種因素的影響,並沒有那麼準確。還是那句話,選擇自己喜歡的加鎖方式,高大上的還是效能高的,自己選擇,沒必要太在意對比。

相關推薦

iOS執行-各種執行簡單介紹

執行緒安全是怎麼產生的 常見比如執行緒內操作了一個執行緒外的非執行緒安全變數,這個時候一定要考慮執行緒安全和同步。 - (void)getIamgeName:(NSMutableArray *)imageNames{//假如每個進來的都是一個執行緒 /*1.im

iOS 個target時候執行報錯

多個target真機執行報錯 This applicationor a bundle itcontains has the same bundle identifier as this appl

Apollo架構體系、Apollo執行原理、Apollo配置中心簡單介紹(一)

筆者在工作中遇到如下問題,隨著程式功能越多,配置檔案不斷增加,一些功能的開關、伺服器地址、介面地址、不同環境的一些配置檔案不同,這些在每次釋出不同環境、更新專案時都比較繁瑣,後來學習微服務時接觸到了Spring Cloud Config配置中心,用了一段時間發現比之前方便不少,但是還是比較繁瑣和麻煩

iOS 各種快取機制的簡單介紹

AppCache類把判斷資料是否過期的邏輯從檢視控制器中抽象出來了,還把快取儲存的位置也抽象出來了。稍後在本章中我們還會修改AppCache,再引入一層快取,內容會儲存在記憶體中。 因為AppCache抽象出了快取的儲存位置,我們就不需要為複製貼上程式碼來獲得應用的快取目錄而操心了。如果應用類似於iHo

可重入內建簡單介紹

每個Java物件都可以用做一個實現同步的鎖,這些鎖被稱為內建鎖或監視器鎖。執行緒在進入同步程式碼塊之前會自動獲取鎖,並且在退出同步程式碼塊時會自動釋放鎖。獲得內建鎖的唯一途徑就是進入由這個鎖保護的同步程式碼塊或方法。 當某個執行緒請求一個由其他執行緒持有的鎖時,發出請求

悲觀與樂觀簡單介紹

1、悲觀鎖,正如其名,它指的是對資料被外界(包括本系統當前的其他事務,以及來自外部系統的事務處理)修改持保守態度,因此,在整個資料處理過程中,將資料處於鎖定狀態。悲觀鎖的實現,往往依靠資料庫提供的鎖機制(也只有資料庫層提供的鎖機制才能真正保證資料訪問的排他性

iOS 執行中的

鎖的分類以及簡單介紹 一. 鎖的分類 互斥鎖 互斥鎖是一種訊號量,一次只允許訪問一個執行緒。如果正在使用互斥鎖並且另一個執行緒試圖獲取它,則該執行緒將阻塞,直到互斥鎖被其原始持有者釋放。如果多個執行緒競爭相同的互斥鎖,則一次只允許一個互斥鎖訪問它。 遞迴鎖定(也是互

iOS 執行 互斥 同步

在iOS中有幾種方法來解決多執行緒訪問同一個記憶體地址的互斥同步問題: 方法一,@synchronized(id anObject),(最簡單的方法) 會自動對引數物件加鎖,保證臨界區內的程式碼執行緒安全 [cpp] view plain copy  prin

ios執行解析

問題:ios 誰能分析下多執行緒死鎖問題,感謝,分析圖一二為什麼是這個結果? (問題帖子連結:http://zhidao.baidu.com/link?url=Lr9sNchrdnCLJdoc73WeHfL3lcu7lBvyKQ2hBrF2jbyM3wkJWeK0

ios執行——(解決執行搶奪同一塊資源的問題)

在iOS中有幾種方法來解決多執行緒訪問同一個記憶體地址的互斥同步問題: 方法一,@synchronized(id anObject),(最簡單的方法) 會自動對引數物件加鎖,保證臨界區內的程式碼執行緒

JAVA執行(三) 執行池和的深度化

 github演示程式碼地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/src/main/java/com/kawa/thread 1.執行緒池  1.1 執行緒池是什麼 Java中的執行緒

Linux執行程式設計---執行間同步(互斥、條件變數、訊號量和讀寫

本篇博文轉自http://zhangxiaoya.github.io/2015/05/15/multi-thread-of-c-program-language-on-linux/ Linux下提供了多種方式來處理執行緒同步,最常用的是互斥鎖、條件變數、訊號量和讀寫鎖。  下面是思維導

執行學習---執行的應用(十一)

Lock比傳統執行緒模型中的synchronized方式更加面向物件,與生活中的鎖類似,鎖本身也應該是一個物件。兩個執行緒執行的程式碼片段要實現同步互斥的效果,它們必須使用同一個Lock物件。鎖是上在代表要操作資源的類的內部方法中,而不是執行緒的程式碼中! 示例程式碼: public c

執行基礎5 Lock

1.同步 * 使用ReentrantLock類的lock()和unlock()方法進行同步 2.通訊 * 使用ReentrantLock類的newCondition()方法可以獲取Condition物件 * 需要等待的時候使用Condition的await()方法, 喚醒的時候用signal()

IOS執行之NSoperation和GCD的比較

GCD是基於c的底層api,NSOperation屬於object-c類。iOS首先引入的是NSOperation,IOS4之後引入了GCD和NSOperationQueue並且其內部是用gcd實現的。 相對於GCD: 1,NSOperation擁有更多的函式可用,具體檢視api。

java執行中顯式的輪詢檢測策略

顯式鎖簡介 java5.0之前,在協調對共享物件的訪問時可以使用的機制只有synchronized和volatile,java5.0增加了一種新的機制:ReentrantLock。 鎖像synchronized同步塊一樣,是一種執行緒同步機制,與synchronized不同的是ReentrantLock提

【JAVA執行問題之死

  一、死鎖是什麼? 舉個例子:兩個人一起吃飯,每個人都拿了一隻筷子,雙方都在等待對方將筷子讓給自己,結果兩個人都吃不了飯。這種情況和計算機中的死鎖情況很相似。 假設有兩個執行緒,互相等待對方釋放佔有的鎖,但是釋放鎖的條件又不可能形成,這時候死鎖就形成了。 還是買票的問題,有的時候時會發生死

執行學習----讀寫的使用(十二)

讀寫鎖      讀寫鎖:分為讀鎖和寫鎖,多個讀鎖不互斥,讀鎖與寫鎖互斥,寫鎖和寫鎖互斥,這是由jvm自己控制的,你只要上好相應的鎖即可。如果你的程式碼只讀資料,可以很多人同時讀,但是不能同時寫,那就讓讀鎖;如果你的程式碼修改資料,只能有一個人在寫,且不能同時讀

gdb除錯執行出現的死

   多執行緒的條件下,程式很容易出現死鎖,此時各個執行緒處於等待狀態,可以通過gdb除錯找到死鎖出現的地方。 例子: #include <stdio.h> #include <pthread.h> #include <uni

C#關於執行執行同步 lock的應用

Form1.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq;