iOS中的鎖(5)

iOS中的鎖(5)

本文主要介紹pthread讀寫鎖,以及自定義一個簡單的讀寫鎖。

1. pthread

1.1 TLS

安全傳輸層協(xié)議(TLS)用于在兩個通信應(yīng)用程序之間提供保密性和數(shù)據(jù)完整性。

該協(xié)議由兩層組成:
TLS 記錄協(xié)議(TLS Record)和 TLS 握手協(xié)議(TLS Handshake)。

傳輸層安全性協(xié)議(Transport Layer Security),縮寫為TLS,及其前身安全套接字(Secure Sockets Layer,縮寫作SSL)是一種安全協(xié)議,目的是為互聯(lián)網(wǎng)通信提供安全及數(shù)據(jù)完整性保障。網(wǎng)景公司(Netscape)在1994年推出首版網(wǎng)頁瀏覽器,網(wǎng)景導(dǎo)航者時,推出HTTP協(xié)議,以SSL進(jìn)行加密,這是SSL的起源。IETF將SSL進(jìn)行標(biāo)準(zhǔn)化,1999年公布第一版TLS標(biāo)準(zhǔn)文件,隨后又公布了RFC5246(2008年8月)與RFC6176(2011年3月)。在瀏覽器、郵箱、即時通訊、VoIP、網(wǎng)絡(luò)傳值等應(yīng)用程序中,廣泛支持這個協(xié)議。主要的網(wǎng)站,如Google、Facebook等也以這個協(xié)議來創(chuàng)建安全連線,發(fā)送數(shù)據(jù)。目前已成為互聯(lián)網(wǎng)上保密同學(xué)的工業(yè)標(biāo)準(zhǔn)。

SSL包含記錄層(Record Layer)和傳輸層,記錄層協(xié)議確定傳輸層數(shù)據(jù)的封裝格式。傳輸層安全協(xié)議使用X.509認(rèn)證,之后利用非對稱加密演算來對通信方做身份認(rèn)證,之后交換對稱密鑰作為會談密鑰(Session Key)。這會談密鑰是用來將通信兩方交換的數(shù)據(jù)做加密,保證兩個應(yīng)用間通信的保密性和可靠性,是客戶與服務(wù)器應(yīng)用之間的通信不被攻擊者竊聽。

1.2 TLS 線程相關(guān)解釋

線程局部存儲(Thread Local Storage,TLS): 是操作系統(tǒng)為線
程單獨提供的私有空間,通常只有有限的容量。Linux系統(tǒng)下
通常通過pthread庫中的 pthread_key_create()、pthread_getspecific()pthread_setspecific()、 pthread_key_delete()。

1.3 互斥鎖

Posix Thread中定義有一套專?用于線程同步的mutex函數(shù)。mutex用于保證在任何時刻,都只能有一個線程訪問該對象。 當(dāng)獲取鎖操作失敗時,線程會進(jìn)入睡眠,等待鎖釋放時被喚醒。

  1. 創(chuàng)建和銷毀
    1. POSIX定義了一個宏PTHREAD_MUTEX_INITIALIZER來靜態(tài)初始化互斥鎖
    2. 初始化:int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
    3. 注銷:pthread_mutex_destroy()
  2. 互斥鎖屬性
    1. 互斥鎖,分為遞歸鎖和非遞歸鎖。
    2. 對于遞歸鎖使用的是PTHREAD_MUTEX_RECURSIVE
  3. 鎖操作
    1. 加鎖:int pthread_mutex_lock(pthread_mutex_t *mutex)
    2. 解鎖:int pthread_mutex_unlock(pthread_mutex_t *mutex)
    3. 嘗試加鎖:int pthread_mutex_trylock(pthread_mutex_t *mutex),在鎖被占用是返回EBUSY,不會掛起線程等待。

2. 讀寫鎖

讀寫鎖實際是一種特殊的自旋鎖,它把對共享資源的訪問者劃分成讀者和寫者,讀者只對共享資源 進(jìn)行讀訪問,寫者則需要對共享資源進(jìn)行寫操作。這種鎖相對于自旋鎖而言,能提高并發(fā)性,因為在多處理器系統(tǒng)中,它允許同時有多個讀者來訪問共享資源,最大可能的讀者數(shù)為實際的邏輯CPU數(shù)。寫者是排他性的,一個讀寫鎖同時只能有一個寫者或多個讀者(與CPU數(shù)相關(guān)),但不能同時既有讀者又有寫者。在讀寫鎖保持期間也是搶占失效的。

如果讀寫鎖當(dāng)前沒有讀者,也沒有寫者,那么寫者可以立刻獲得讀寫鎖,否則它必須自旋在那里,直到?jīng)]有任何寫者或讀者。

如果讀寫鎖沒有寫者,那么讀者可以立即獲得該讀寫鎖,否則讀者必須自旋在那里,直到寫者釋放該讀寫鎖。

一次只有一個線程可以占有寫模式的讀寫鎖,但是可以有多個線程同時占有讀模式的讀寫鎖。正是因為這個特性,當(dāng)讀寫鎖是寫加鎖狀態(tài)時,在這個鎖被解鎖之前,所有試圖對這個鎖加鎖的線程都會被阻塞。當(dāng)讀寫鎖在讀加鎖狀態(tài)時,所有試圖以讀模式對它進(jìn)行加鎖的線程都可以得到訪問權(quán),但是如果線程希望以寫模式對此鎖進(jìn)行加鎖,它必須直到所有的線程釋放鎖。通常當(dāng)讀寫鎖處于讀模式鎖住狀態(tài)時,如果有另外線程試圖以寫模式加鎖,讀寫鎖通常會阻塞隨后的讀模式鎖請求,這樣可以避免讀模式鎖?期占用,而等待的寫模式鎖請求?期阻塞。讀寫鎖適合于對數(shù)據(jù)結(jié)構(gòu)的讀次數(shù)比寫次數(shù)多得多的情況。因為,讀模式鎖定時可以共享,以寫模式鎖住時意味著獨占, 所以讀寫鎖又叫共享-獨占鎖。

2.1 iOS中的的讀寫鎖

讀寫鎖適合于對數(shù)據(jù)結(jié)構(gòu)的讀次數(shù)比寫次數(shù)多得多的情況。因為,讀模式鎖定時可以共享,以寫模式鎖住時意味著獨占,所以讀寫鎖又叫共享-獨占鎖。

2.1.1 初始化讀寫鎖

#include <pthread.h>
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
  • 初始化成功則返回0, 出錯則返回錯誤編號。
  • 同互斥量以上,在釋放讀寫鎖占用的內(nèi)存之前,需要先通過pthread_rwlock_destroy對讀寫鎖進(jìn)行清理工作,釋放由init分配的資源。

2.1.2 讀寫鎖操作

  1. 讀鎖:int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
  2. 寫鎖:int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
  3. 解鎖:int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
  • 成功則返回0,出錯則返回錯誤編號。
  • 對于讀鎖和寫鎖是會阻塞線程的
  1. 嘗試讀鎖:int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
  2. 嘗試寫鎖:int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
  • 成功則返回0,出錯則返回錯誤編號。
  • 非阻塞的獲取鎖操作,如果可以獲取則返回0,否則返回錯誤的EBUSY。

2.2 自定義讀寫鎖

2.2.1 自定義讀寫鎖代碼

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface MYRWLock : NSObject
// 讀數(shù)據(jù)
- (id)my_objectForKey:(NSString *)key;
// 寫數(shù)據(jù)
- (void)my_setObject:(id)obj forKey:(NSString *)key;
@end

NS_ASSUME_NONNULL_END


#import "MYRWLock.h"

@interface MYRWLock ()
// 定義一個并發(fā)隊列:
@property (nonatomic, strong) dispatch_queue_t concurrent_queue;
// 用戶數(shù)據(jù)中心, 可能多個線程需要數(shù)據(jù)訪問:
@property (nonatomic, strong) NSMutableDictionary *dataCenterDic;
@end

@implementation MYRWLock

- (id)init{
    self = [super init];
    if (self){
        // 創(chuàng)建一個并發(fā)隊列:
        self.concurrent_queue = dispatch_queue_create("com.my.read_write_queue", DISPATCH_QUEUE_CONCURRENT);
        // 創(chuàng)建數(shù)據(jù)字典:
        self.dataCenterDic = [NSMutableDictionary dictionary];
    }
    return self;
}

#pragma mark - 讀數(shù)據(jù)
- (id)my_objectForKey:(NSString *)key{
    __block id obj;
    // 同步讀取指定數(shù)據(jù):
    dispatch_sync(self.concurrent_queue, ^{
        obj = [self.dataCenterDic objectForKey:key];
    });
    return obj;
}

#pragma mark - 寫數(shù)據(jù)
- (void)my_setObject:(id)obj forKey:(NSString *)key{
    // 異步柵欄調(diào)用設(shè)置數(shù)據(jù):
    dispatch_barrier_async(self.concurrent_queue, ^{
        [self.dataCenterDic setObject:obj forKey:key];
    });
}

@end

這里在寫操作的時候,使用柵欄函數(shù)進(jìn)行阻塞,讀的時候不做限制。

2.2.2 使用示例


@property (nonatomic, strong) MYRWLock *rwLock;

- (void)testRWLock {
    self.rwLock = [[MYRWLock alloc] init];
    
    dispatch_queue_t queue = dispatch_queue_create("com.test.rwlock", DISPATCH_QUEUE_CONCURRENT);
    
    for (int i = 0; i<10; i++) {
        dispatch_async(queue, ^{
            NSString *str = [NSString stringWithFormat:@"rw_test%d",i];
            NSLog(@"寫%@---%@",str, [NSThread currentThread]);
            [self.rwLock my_setObject:str forKey:@"rwKey"];
        });
    }
    
    for (int i = 0; i<10; i++) {
        dispatch_async(queue, ^{
            NSLog(@"讀 %@---%@",[self.rwLock my_objectForKey:@"rwKey"], [NSThread currentThread]);
        });
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 歡迎閱讀iOS探索系列(按序閱讀食用效果更加)iOS探索 alloc流程iOS探索 內(nèi)存對齊&malloc源碼iO...
    呂子喬_eabd閱讀 1,206評論 0 2
  • 前言 在多線程開發(fā)中,常會遇到多個線程訪問修改數(shù)據(jù)。為了防止數(shù)據(jù)不一致或數(shù)據(jù)污染,通常采用加鎖機(jī)制來保證線程安全。...
    趙夢楠閱讀 1,162評論 0 5
  • 概念 自旋鎖: 線程反復(fù)檢查鎖變量是否可用。由于線程在這一過程中保持執(zhí)行, 因此是一種忙等待。一旦獲取了自旋鎖,線...
    MonKey_Money閱讀 1,014評論 2 1
  • 前言 ??在使用多線程的時候多個線程可能會訪問同一塊資源,這樣就很容易引發(fā)數(shù)據(jù)錯亂和數(shù)據(jù)安全等問題。解決資源爭用,...
    小盟城主閱讀 1,477評論 0 3
  • 本文節(jié)選自成長手冊 文章推薦和參考深入理解 iOS 開發(fā)中的鎖pthread的各種同步機(jī)制 多線程編程被普遍認(rèn)為復(fù)...
    百草紀(jì)閱讀 2,922評論 1 9

友情鏈接更多精彩內(nèi)容