談談iOS中的幾種鎖_IOS

來源:互聯網
上載者:User

1 前言

近日工作不是太忙,剛好有時間瞭解一些其他東西,本來打算今天上午去體檢,但是看看天氣還是明天再去吧,也有很大一個原因:就是周六沒有預約上!閑話少說,這裡簡單對鎖來個簡單介紹分享。

2 目錄

  1. 第一部分:什麼是鎖
  2. 第二部分:鎖的分類
  3. 第三部分:鎖的作用
  4. 第四部分:iOS中鎖的實現

第一部分:什麼是鎖

從小就知道鎖,就是家裡門上的那個鎖,用來防止盜竊的鎖。它還有鑰匙,用於開鎖。不過這裡的鎖,並不是小時候認知的鎖,而是站在程式員的角度的鎖。這裡我就按照我的理解來介紹一下鎖。

在電腦科學中,鎖是一種同步機制,用於在存在多線程的環境中實施對資源的訪問限制。你可以理解成它用於排除並發的一種策略。看例子

if (lock == 0) {lock = myPID;}

上面這段代碼並不能保證這個任務有個鎖,因此它可以在同一時間被多個任務執行。這個時候就有可能多個任務都檢測到lock是閒置,因此兩個或者多個任務都將嘗試設定lock,而不知道其他的任務也在嘗試設定lock。這個時候就會出問題了。
再看看這段代碼:

class Acccount {long val = 0; //這裡不可在其他方法修改,只能通過add/minus修改object thisLock = new object();public void add(const long x) {lock(thisLock) {  val +=x;}}public void minus(const long x) {lock(thisLock) {  val -=x;  }}}

這樣就能防止多個任務去修改val了,(這裡注意,如果val是public的,那個也會導致一些問題)。

第二部分:鎖的分類

鎖根據不同的性質可以分成不同的類。

在WiKiPedia介紹中,一般的鎖都是建議鎖,也就四每個任務去訪問公用資源的時候,都需要取得鎖的資訊,再根據鎖資訊來確定是否可以存取。若存取對應資訊,鎖的狀態會改變為鎖定,因此其他線程不會訪問該資源,當結束訪問時,鎖會釋放,允許其他任務訪問。有些系統有強制鎖,若未經授權的鎖訪問鎖定的資料,在訪問時就會產生異常。
在iOS中,鎖分為遞迴鎖、條件鎖、分布式鎖、一般鎖(這裡是看著NSLock類裡面的分類劃分的)。
對於資料庫的鎖分類:

分類方式 分類
按鎖的粒度劃分 表級鎖、行級鎖、頁級鎖
按鎖的層級劃分 共用鎖定、獨佔鎖定
按加鎖方式劃分 自動鎖、顯示鎖
按鎖的使用方式劃分 樂觀鎖、悲觀鎖
按操作劃分 DML鎖、DDL鎖

這裡就不在詳細介紹了,感興趣的大家可以自己查閱相關資料。

第三部分:鎖的作用

這個比較通俗來講:就是為了防止在多線程(多任務)的情況下對共用資源(臨界資源)的髒讀或者髒寫。也可以理解為:執行多線程時用於強行限制資源訪問的同步機制,即並發控制中保證互斥的要求。

第四部分:iOS中鎖的實現

先看看iOS中NSLock類的.h檔案。這裡就不在寫上來了。從代碼中可以看出,該類分成了幾個子類:NSLock、NSConditionLock、NSRecursiveLock以及NSCondition。然後有一個NSLocking的協議:

@protocol NSLocking- (void)lock;- (void)unlock;@end

這幾個子類都遵循了NSLock的協議,這裡簡單介紹一下其中的幾個方法:

對於tryLock方法,嘗試擷取一個鎖,並且立刻返回Bool值,YES表示擷取了鎖,NO表示沒有擷取鎖失敗。 lockBeforeDate:方法,在某個時刻之前擷取鎖,如果擷取成功,則返回YES,NO表示擷取鎖失敗。接下來就讓我們看一下iOS中實現鎖的方式:

方式1 使用NSLock類

- (void)nslockDemo {  NSLock *myLock = [[NSLock alloc] init];  _testLock = [[TestLock alloc] init];  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    [myLock lock];    [_testLock method1];    sleep(5);    [myLock unlock];    if ([myLock tryLock]) {      NSLog(@"可以獲得鎖");    }else {      NSLog(@"不可以獲得所");    }  });  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    sleep(1);    if ([myLock tryLock]) {      NSLog(@"---可以獲得鎖");    }else {      NSLog(@"----不可以獲得所");    }    [myLock lock];    [_testLock method2];    [myLock unlock];  });}

方式2 使用@synchorize

- (void)synchronizeDemo {  _testLock = [[TestLock alloc] init];  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    @synchronized (_testLock) {      [_testLock method1];      sleep(5);    }  });  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    sleep(1);    @synchronized (_testLock) {            [_testLock method2];    }  });}

對於synchorize指令中使用的testLock為該鎖標示,只有標示相同的時候才滿足鎖的效果。它的優點是不用顯式地建立鎖,便可以實現鎖的機制。但是它會隱式地添加例外處理常式來保護代碼,該程式在拋出異常的時候自動釋放鎖。

方式3 使用gcd

- (void)gcdDemo {  _testLock = [[TestLock alloc] init];  dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);    [_testLock method1];    sleep(5);    dispatch_semaphore_signal(semaphore);  });  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    sleep(1);    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);    [_testLock method2];    dispatch_semaphore_signal(semaphore);  });}

方式4 使用phtread

- (void)pthreadDemo {  _testLock = [[TestLock alloc] init];    __block pthread_mutex_t mutex;  pthread_mutex_init(&mutex, NULL);    //線程1  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    pthread_mutex_lock(&mutex);    [_testLock method1];    sleep(5);    pthread_mutex_unlock(&mutex);  });    //線程2  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    sleep(1);    pthread_mutex_lock(&mutex);    [_testLock method2];    pthread_mutex_unlock(&mutex);  });}

pthread_mutex_t定義在pthread.h,所以記得#include。

3 效能對比

這裡簡單寫一個小程式來進行四種方式的效能對比,這裡再固定次數內進行了加鎖解鎖,然後輸出用時,結果如下(測試1、2執行次數不一樣:測試1 < 測試2):

測試1

2016-11-05 15:27:52.595 LockDemo[4394:202297] NSLock times:0.871843
2016-11-05 15:27:56.335 LockDemo[4394:202297] synthorize times:3.738939
2016-11-05 15:27:56.691 LockDemo[4394:202297] gcd times:0.355344
2016-11-05 15:27:57.328 LockDemo[4394:202297] pthread times:0.636815
2016-11-05 15:27:57.559 LockDemo[4394:202297] OSSPinLock times:0.231013
2016-11-05 15:27:57.910 LockDemo[4394:202297] os_unfair_lock times:0.350615

測試2

2016-11-05 15:30:54.123 LockDemo[4454:205180] NSLock times:1.908103
2016-11-05 15:31:02.112 LockDemo[4454:205180] synthorize times:7.988547
2016-11-05 15:31:02.905 LockDemo[4454:205180] gcd times:0.792113
2016-11-05 15:31:04.372 LockDemo[4454:205180] pthread times:1.466987
2016-11-05 15:31:04.870 LockDemo[4454:205180] OSSPinLock times:0.497487
2016-11-05 15:31:05.637 LockDemo[4454:205180] os_unfair_lock times:0.767569

這裡還測試了OSSPinLock(此類已經被os_unfair_lock所替代)。結果如下:

synthorize > NSLock > pthread > gcd > os_unfair_lock >OSSPinLock

這裡:

synthorize內部會添加異常處理,所以耗時。

pthread_mutex底層API,處理能力不錯。

gcd系統封裝的C代碼效果比pthread好。

4 總結

簡單就介紹這麼多。

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援雲棲社區。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.