欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:cocoa iOS--鎖的學習

柚子快報邀請碼778899分享:cocoa iOS--鎖的學習

http://yzkb.51969.com/

iOS--鎖的學習

鎖的介紹線程安全

鎖的分類自旋鎖和互斥鎖OSSpinLockos_unfair_lockpthread_mutexpthread_mutex的屬性

NSLockNSRecursiveLockNSConditionNSConditionLockdispatch_semaphoredispatch_queue@synchronizedatomicpthread_rwlock:讀寫鎖dispatch_barrier_async

鎖的性能比較

鎖的介紹

主要參考了iOS多線程安全-13種線程鎖? 在iOS開發(fā)中,鎖是一種用于管理并發(fā)訪問共享資源的機制。多個線程可以同時訪問共享資源,但在某一時刻只允許一個線程對資源進行讀取或修改,以避免數(shù)據(jù)競爭和不一致性。 鎖的主要目的是確保在給定時間內(nèi)只有一個線程可以進入被鎖定的代碼塊或臨界區(qū)。當一個線程獲得了鎖并進入臨界區(qū)時,其他嘗試獲取鎖的線程會被阻塞,直到該線程釋放鎖。這樣可以保證在臨界區(qū)內(nèi)的代碼只會被一個線程執(zhí)行,從而避免競態(tài)條件和數(shù)據(jù)不一致性的問題。

在iOS中,有多種鎖機制可供選擇,每種鎖機制都有其特定的適用場景和性能特征。一些常見的鎖機制包括: 互斥鎖(Mutex):例如NSLock、pthread_mutex等?;コ怄i提供了基本的線程同步機制,通過對臨界區(qū)加鎖和解鎖來確保同一時間只有一個線程可以訪問。 遞歸鎖(Recursive Lock):例如NSRecursiveLock、pthread_mutex_recursive等。遞歸鎖允許同一線程多次獲取鎖,避免了死鎖情況。 條件鎖(Condition Lock):例如NSConditionLock、pthread_cond等。條件鎖在某些特定條件下才允許線程繼續(xù)執(zhí)行,否則線程會被阻塞。 信號量(Semaphore):例如dispatch_semaphore。信號量是一種更為通用的同步機制,可以用于控制多個線程的并發(fā)數(shù)量。 自旋鎖(Spin Lock):例如os_unfair_lock、OSSpinLock(已被棄用)等。自旋鎖在等待鎖時不會將線程阻塞,而是通過循環(huán)忙等的方式嘗試獲取鎖,適用于短時間內(nèi)鎖的競爭概率較低的情況。

線程安全

線程安全是指在多線程環(huán)境下,程序能夠正確地處理共享數(shù)據(jù)并保證數(shù)據(jù)的一致性和正確性。 在多線程編程中,多個線程可以同時訪問和修改共享的數(shù)據(jù)。如果沒有適當?shù)耐綑C制和線程安全的設計,可能會出現(xiàn)以下問題:

競態(tài)條件(Race Condition):多個線程同時對同一數(shù)據(jù)進行讀寫操作,導致結果依賴于線程執(zhí)行的順序,從而得到不確定的結果。數(shù)據(jù)競爭(Data Race):多個線程同時訪問和修改共享數(shù)據(jù),其中至少一個是寫操作,導致未定義的行為。

這里用一個比較經(jīng)典的例子,具體參考iOS多線程安全-13種線程鎖?

//賣票演示

- (void)ticketTest{

self.ticketsCount = 50;

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

for (NSInteger i = 0; i < 5; i++) {

dispatch_async(queue, ^{

for (int i = 0; i < 10; i++) {

[self sellingTickets];

}

});

}

}

//賣票

- (void)sellingTickets{

int oldMoney = self.ticketsCount;

sleep(.2);

oldMoney -= 1;

self.ticketsCount = oldMoney;

NSLog(@"當前剩余票數(shù)-> %d", oldMoney);

}

運行結果如圖:

這里是一個典型的數(shù)據(jù)競爭問題,當多個線程同時對一個共享數(shù)據(jù)進行讀寫操作是很有可能會發(fā)生數(shù)據(jù)競爭,為了避免這種情況,我們往往通過線程同步來保證線程安全。實現(xiàn)線程同步的方法很多,鎖就是一種比較常見的用法 ;

鎖的分類

鎖是實現(xiàn)線程同步和保證數(shù)據(jù)訪問的一種機制,在多線程編程中起著重要的作用。根據(jù)實現(xiàn)方式和特性,鎖可以分為幾個不同的分類:

互斥鎖(Mutex Lock):互斥鎖是最常見和基本的鎖類型,用于實現(xiàn)互斥訪問共享資源。它提供了兩個狀態(tài):鎖定(被一個線程持有)和解鎖(無線程持有)。只有一個線程可以持有互斥鎖,其他線程在獲取鎖之前會被阻塞?;コ怄i可以防止多個線程同時訪問臨界區(qū),從而保證數(shù)據(jù)的一致性。讀寫鎖(Read-Write Lock):讀寫鎖也稱為共享-獨占鎖,它允許多個線程同時讀取共享資源,但只允許一個線程進行寫操作。讀操作之間不會互斥,而讀操作與寫操作之間是互斥的。讀寫鎖適用于讀多寫少的場景,可以提高并發(fā)性能。自旋鎖(Spin Lock):自旋鎖是一種忙等待鎖,它使用循環(huán)來反復檢查鎖是否被釋放,而不是將線程阻塞。當一個線程發(fā)現(xiàn)自旋鎖被其他線程持有時,它會一直循環(huán)等待,直到自旋鎖可用。自旋鎖適用于臨界區(qū)很小且短時間內(nèi)會釋放的情況。條件變量(Condition Variable):條件變量用于線程之間的等待和通知機制。它與互斥鎖結合使用,允許一個線程等待某個條件成立并在條件滿足時通知其他線程。等待條件的線程會釋放互斥鎖,以便其他線程可以訪問臨界區(qū)。條件變量常用于生產(chǎn)者-消費者問題等場景。屏障(Barrier):屏障用于多個線程在某個點上等待,直到所有線程都到達該點后才繼續(xù)執(zhí)行。它可以用于同步多個線程的操作,確保線程在達到某個階段之前都等待其他線程。

自旋鎖和互斥鎖

自旋鎖(Spin Lock): 自旋鎖是一種忙等待鎖,它使用循環(huán)來反復檢查鎖的狀態(tài),直到獲取到鎖為止。自旋鎖的特點如下:

自旋鎖適用于臨界區(qū)很小且短時間內(nèi)會釋放的情況,因為它需要持續(xù)占用CPU資源來進行自旋等待。自旋鎖不會導致線程的阻塞和切換,所以對于短時間內(nèi)能夠獲取到鎖的情況,自旋鎖的性能較好。自旋鎖不會改變線程的調(diào)度順序,因此在高優(yōu)先級線程和低優(yōu)先級線程之間,可能會導致優(yōu)先級反轉(zhuǎn)的問題。

互斥鎖是一種常見的線程同步機制,用于實現(xiàn)互斥訪問共享資源。在iOS中,常用的互斥鎖有NSLock和NSRecursiveLock?;コ怄i的特點如下:

互斥鎖允許一個線程持有鎖,其他線程在獲取鎖之前會被阻塞,從而實現(xiàn)對臨界區(qū)的互斥訪問?;コ怄i會導致線程的阻塞和切換,所以對于長時間占用鎖或等待時間不確定的情況,互斥鎖的性能可能較差?;コ怄i可以解決優(yōu)先級反轉(zhuǎn)的問題,因為它可以改變線程的調(diào)度順序,讓優(yōu)先級高的線程優(yōu)先獲取鎖。

互斥鎖:線程會從sleep(加鎖)——>running(解鎖),過程中有上下文的切換,cpu的搶占,信號的發(fā)送等開銷。 自旋鎖:線程一直是running(加鎖——>解鎖),死循環(huán)檢測鎖的標志位,機制不復雜。 對比 互斥鎖的起始原始開銷要高于自旋鎖,但是基本是一勞永逸,臨界區(qū)持鎖時間的大小并不會對互斥鎖的開銷造成影響,而自旋鎖是死循環(huán)檢測,加鎖全程消耗cpu,起始開銷雖然低于互斥鎖,但是隨著持鎖時間,加鎖的開銷是線性增長。

OSSpinLock

OSSpinLock是iOS舊版本中提供的一種自旋鎖(Spin Lock)實現(xiàn)。它通過忙等待的方式來獲取鎖,并且不會導致線程的阻塞和切換。不過需要注意的是,自旋鎖在iOS 10之后已被標記為廢棄,因為它存在優(yōu)先級反轉(zhuǎn)和性能問題。推薦使用更現(xiàn)代的互斥鎖實現(xiàn),如os_unfair_lock和pthread_mutex等。 使用時需要導入頭文件#import

os_unfair_lock

os_unfair_lock是iOS 10及以上版本引入的一種互斥鎖(Mutex Lock)實現(xiàn),用于實現(xiàn)線程同步和保護共享資源的訪問。相比于舊版本中的自旋鎖(OSSpinLock),os_unfair_lock采用了更高級的算法來解決優(yōu)先級反轉(zhuǎn)和性能問題。 os_unfair_lock的特點如下:

os_unfair_lock是一種互斥鎖,只能由一個線程持有,其他線程在獲取鎖之前會被阻塞。它可以解決優(yōu)先級反轉(zhuǎn)問題,確保高優(yōu)先級線程在等待鎖時能夠優(yōu)先獲取。os_unfair_lock的實現(xiàn)采用了更高級的算法,避免了自旋等待,減少了不必要的CPU開銷。os_unfair_lock的性能通常比舊版自旋鎖(OSSpinLock)更好,尤其在高并發(fā)情況下。 需要導入頭文件#import

@implementation ViewController {

os_unfair_lock _lock ;

}

- (void)viewDidLoad {

[super viewDidLoad];

[self ticketTest] ;

}

//賣票演示

- (void)ticketTest{

self.ticketsCount = 50;

//os_unfair_lock lock = OS_UNFAIR_LOCK_INIT ;

_lock = OS_UNFAIR_LOCK_INIT ;

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

for (NSInteger i = 0; i < 5; i++) {

dispatch_async(queue, ^{

for (int i = 0; i < 10; i++) {

[self sellingTickets];

}

});

}

}

//賣票

- (void)sellingTickets{

os_unfair_lock_lock(&_lock) ;

int oldMoney = self.ticketsCount;

sleep(.2);

oldMoney -= 1;

self.ticketsCount = oldMoney;

NSLog(@"當前剩余票數(shù)-> %d", oldMoney);

os_unfair_lock_unlock(&_lock) ;

}

@end

要注意一下,通常不建議將 os_unfair_lock 直接作為屬性來使用。os_unfair_lock 是一個結構體,不具備 Objective-C 對象的特性,因此不適合直接作為屬性。

pthread_mutex

pthread_mutex 是 POSIX 線程庫中提供的一種互斥鎖(mutex)類型,用于實現(xiàn)線程同步和互斥訪問共享資源。 主要的 pthread_mutex 函數(shù)如下:

pthread_mutex_init:用于初始化互斥鎖,并指定互斥鎖的屬性??梢允褂?NULL 作為第二個參數(shù)來使用默認屬性。pthread_mutex_destroy:用于銷毀互斥鎖。pthread_mutex_lock:加鎖操作,將互斥鎖加鎖,如果互斥鎖已經(jīng)被其他線程鎖定,則當前線程被阻塞直到互斥鎖可用。pthread_mutex_trylock:嘗試加鎖操作,如果互斥鎖已經(jīng)被其他線程鎖定,則該操作會立即返回,而不會阻塞當前線程。pthread_mutex_unlock:解鎖操作,釋放互斥鎖,允許其他線程獲得鎖。

@implementation ViewController {

// os_unfair_lock _lock ;

pthread_mutex_t _lock ;

}

- (void)viewDidLoad {

[super viewDidLoad];

[self ticketTest] ;

}

//賣票演示

- (void)ticketTest{

self.ticketsCount = 50;

//os_unfair_lock lock = OS_UNFAIR_LOCK_INIT ;

//初始化鎖屬性

pthread_mutexattr_t attr ;

pthread_mutexattr_init(&attr) ;

pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) ;

pthread_mutex_init(&_lock, &attr) ;//第二個參數(shù)可以為NULL,表示使用默認屬性PTHREAD_MUTEX_NORMAL

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

for (NSInteger i = 0; i < 5; i++) {

dispatch_async(queue, ^{

for (int i = 0; i < 10; i++) {

[self sellingTickets];

}

});

}

}

//賣票

- (void)sellingTickets{

// os_unfair_lock_lock(&_lock) ;

pthread_mutex_lock(&_lock) ;

int oldMoney = self.ticketsCount;

sleep(.2);

oldMoney -= 1;

self.ticketsCount = oldMoney;

NSLog(@"當前剩余票數(shù)-> %d", oldMoney);

// os_unfair_lock_unlock(&_lock) ;

pthread_mutex_unlock(&_lock) ;

}

@end

pthread_mutex的屬性

pthread_mutexattr_settype:設置互斥鎖的類型。常見選項有:

PTHREAD_MUTEX_NORMAL:普通互斥鎖,不支持遞歸。PTHREAD_MUTEX_RECURSIVE:遞歸互斥鎖,允許同一線程多次獲得鎖。PTHREAD_MUTEX_ERRORCHECK:錯誤檢查互斥鎖,會檢測多次鎖定同一互斥鎖的錯誤。PTHREAD_MUTEX_DEFAULT:根據(jù)實現(xiàn)的默認類型設置互斥鎖。

NSLock

**NSLock是對mutex普通鎖的封裝。**pthread_mutex_init(mutex, NULL); NSLock 遵循 NSLocking 協(xié)議。Lock 方法是加鎖,unlock 是解鎖,tryLock 是嘗試加鎖,如果失敗的話返回 NO,lockBeforeDate: 是在指定Date之前嘗試加鎖,如果在指定時間之前都不能加鎖,則返回NO

@protocol NSLocking

- (void)lock;

- (void)unlock;

@end

@interface NSLock : NSObject {

@private

void *_priv;

}

- (BOOL)tryLock;

- (BOOL)lockBeforeDate:(NSDate *)limit;

@property (nullable, copy) NSString *name

@end

@implementation ViewController {

// os_unfair_lock _lock ;

// pthread_mutex_t _lock ;

}

- (void)viewDidLoad {

[super viewDidLoad];

[self ticketTest] ;

}

//賣票演示

- (void)ticketTest{

self.ticketsCount = 50;

//os_unfair_lock lock = OS_UNFAIR_LOCK_INIT ;

//初始化鎖屬性

// pthread_mutexattr_t attr ;

// pthread_mutexattr_init(&attr) ;

// pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) ;

// pthread_mutex_init(&_lock, &attr) ;//第二個參數(shù)可以為NULL,表示使用默認屬性PTHREAD_MUTEX_NORMAL

self.lock = [[NSLock alloc] init] ;

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

for (NSInteger i = 0; i < 5; i++) {

dispatch_async(queue, ^{

for (int i = 0; i < 10; i++) {

[self sellingTickets];

}

});

}

}

//賣票

- (void)sellingTickets{

// os_unfair_lock_lock(&_lock) ;

// pthread_mutex_lock(&_lock) ;

[self.lock lock] ;

int oldMoney = self.ticketsCount;

sleep(.2);

oldMoney -= 1;

self.ticketsCount = oldMoney;

NSLog(@"當前剩余票數(shù)-> %d", oldMoney);

// os_unfair_lock_unlock(&_lock) ;

// pthread_mutex_unlock(&_lock) ;

[self.lock unlock] ;

}

//- (instancetype)init {

// self = [super init];

// if (self) {

// _lock = [[NSLock alloc] init];

// }

// return self;

//}

//- (void)lock {

// [_lock lock];

//}

//

//- (void)unlock {

// [_lock unlock];

//}

@end

NSRecursiveLock

NSRecursiveLock是對mutex遞歸鎖的封裝,API跟NSLock基本一致

- (void)ticketTest{

self.ticketsCount = 50;

//os_unfair_lock lock = OS_UNFAIR_LOCK_INIT ;

//初始化鎖屬性

// pthread_mutexattr_t attr ;

// pthread_mutexattr_init(&attr) ;

// pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) ;

// pthread_mutex_init(&_lock, &attr) ;//第二個參數(shù)可以為NULL,表示使用默認屬性PTHREAD_MUTEX_NORMAL

self.lock = [[NSRecursiveLock alloc] init] ;

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

for (NSInteger i = 0; i < 5; i++) {

dispatch_async(queue, ^{

for (int i = 0; i < 10; i++) {

[self sellingTickets];

}

});

}

}

//賣票

- (void)sellingTickets{

// os_unfair_lock_lock(&_lock) ;

// pthread_mutex_lock(&_lock) ;

[self.lock lock] ;

int oldMoney = self.ticketsCount;

sleep(.2);

oldMoney -= 1;

self.ticketsCount = oldMoney;

NSLog(@"當前剩余票數(shù)-> %d", oldMoney);

// os_unfair_lock_unlock(&_lock) ;

// pthread_mutex_unlock(&_lock) ;

[self.lock unlock] ;

}

NSCondition

NSCondition是對mutex和cond的封裝,更加面向?qū)ο?;

@interface NSCondition : NSObject

- (void)wait;

- (BOOL)waitUntilDate:(NSDate *)limit;

- (void)signal;

- (void)broadcast;

@property (nullable, copy) NSString *name;

@end

NSCondition 類繼承自 NSObject 并遵循 NSLocking 協(xié)議。wait 方法用于使當前線程等待,直到接收到信號。 waitUntilDate: 方法使當前線程等待,直到接收到信號或者指定的日期超時。signal 方法用于喚醒一個等待中的線程。broadcast 方法用于喚醒所有等待中的線程。name 屬性是一個可選的字符串,用于標識 NSCondition 對象的名稱。

// 線程1

// 刪除數(shù)組中的元素

- (void)__remove

{

[self.condition lock];

if (self.data.count == 0) {

// 等待

[self.condition wait];

}

[self.data removeLastObject];

NSLog(@"刪除了元素");

[self.condition unlock];

}

// 線程2

// 往數(shù)組中添加元素

- (void)__add

{

[self.condition lock];

sleep(1);

[self.data addObject:@"Test"];

NSLog(@"添加了元素");

// 信號

[self.condition signal];

[self.condition unlock];

}

我的想法是這類對象有兩種線程等待的方式,一種是wait–signal方式,一種是lock–unlock方式 ;

NSConditionLock

NSConditionLock是對NSCondition的進一步封裝,可以設置具體的條件值

@interface NSConditionLock : NSObject {

- (instancetype)initWithCondition:(NSInteger)condition;

@property (readonly) NSInteger condition;

- (void)lockWhenCondition:(NSInteger)condition;

- (BOOL)tryLock;

- (BOOL)tryLockWhenCondition:(NSInteger)condition;

- (void)unlockWithCondition:(NSInteger)condition;

- (BOOL)lockBeforeDate:(NSDate *)limit;

- (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit;

@property (nullable, copy) NSString *name;

@end

dispatch_semaphore

ispatch_semaphore 是 Grand Central Dispatch (GCD) 中的一個信號量機制,用于控制并發(fā)訪問共享資源的線程數(shù)量。這個之前GCD中講過了 ;

dispatch_queue

使用GCD的串行隊列也可以實現(xiàn)線程同步的

@synchronized

@synchronized 是 Objective-C 中用于實現(xiàn)線程安全的關鍵字之一。它提供了一種簡單的方式來保護共享資源,以防止多個線程同時訪問和修改該資源。 使用 @synchronized 的基本語法如下:

@synchronized (object) {

// 同步的代碼塊

// ...

}

@synchronized 關鍵字的工作原理是,在進入 @synchronized 代碼塊之前,它會獲取 object 的互斥鎖,以確保同一時間只有一個線程可以進入該代碼塊。當線程離開 @synchronized 代碼塊時,它會釋放鎖,允許其他線程繼續(xù)進入。

關于@synchronized 的底層原理可以去深入看看,但平時使用只要知道它會在代碼塊開頭加鎖,代碼塊末尾解鎖就行了

atomic

在Objective-C中,atomic是一種屬性修飾符,用于指定屬性的原子性。當一個屬性被聲明為atomic時,它意味著在對該屬性進行讀取和寫入操作時,將會保證操作的原子性。 原子性是指一個操作要么完全執(zhí)行,要么完全不執(zhí)行,不存在執(zhí)行過程中被中斷的情況。在多線程環(huán)境下,使用atomic修飾符可以確保對屬性的讀取和寫入操作是線程安全的。 當屬性被聲明為atomic時,編譯器會自動生成相關的同步代碼,以確保對屬性的訪問是原子操作。這樣可以防止多個線程同時對同一個屬性進行讀寫操作,避免出現(xiàn)數(shù)據(jù)競爭和不一致的情況。 需要注意的是,雖然atomic提供了一定程度的線程安全性,但它并不能完全保證線程安全。在高并發(fā)的多線程環(huán)境中,仍然需要額外的同步機制來確保數(shù)據(jù)的一致性和正確性。 相比之下,另一個屬性修飾符nonatomic則表示屬性是非原子的,它不會提供自動的線程安全保護。在多線程環(huán)境下,使用nonatomic修飾符可以提高性能,但需要開發(fā)人員自行處理線程安全問題。 總之,atomic屬性修飾符用于指定屬性的原子性,提供一定程度的線程安全性。在多線程環(huán)境中,可以使用atomic來確保對屬性的讀取和寫入操作是原子的,但仍需要注意其他的線程安全問題。

pthread_rwlock:讀寫鎖

//初始化鎖

pthread_rwlock_t lock;

pthread_rwlock_init(&_lock, NULL);

//讀加鎖

pthread_rwlock_rdlock(&_lock);

//讀嘗試加鎖

pthread_rwlock_trywrlock(&_lock)

//寫加鎖

pthread_rwlock_wrlock(&_lock);

//寫嘗試加鎖

pthread_rwlock_trywrlock(&_lock)

//解鎖

pthread_rwlock_unlock(&_lock);

//銷毀

pthread_rwlock_destroy(&_lock);

pthread_rwlock 是 POSIX 線程庫中的讀寫鎖(read-write lock)機制。它提供了一種多讀單寫的并發(fā)訪問控制機制,允許多個線程同時讀取共享資源,但只允許一個線程進行寫操作。 使用 pthread_rwlock 可以實現(xiàn)以下功能:

多讀單寫控制:多個線程可以同時獲取讀鎖(讀取共享資源),但只有一個線程可以獲取寫鎖(修改共享資源)。讀寫互斥:在寫鎖被持有期間,其他線程無法獲取讀鎖,以確保數(shù)據(jù)一致性。

dispatch_barrier_async

GCD中也有 ;

鎖的性能比較

性能從高到低排序

1、os_unfair_lock 2、OSSpinLock 3、dispatch_semaphore 4、pthread_mutex 5、dispatch_queue(DISPATCH_QUEUE_SERIAL) 6、NSLock 7、NSCondition 8、pthread_mutex(recursive) 9、NSRecursiveLock 10、NSConditionLock 11、@synchronized

柚子快報邀請碼778899分享:cocoa iOS--鎖的學習

http://yzkb.51969.com/

相關閱讀

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權,聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19167723.html

發(fā)布評論

您暫未設置收款碼

請在主題配置——文章設置里上傳

掃描二維碼手機訪問

文章目錄