簡體   English   中英

是否在同步GCD隊列上設置了阻止阻塞和暫停其他隊列的阻塞?

[英]Does puting a block on a sync GCD queue locks that block and pauses the others?

我讀到應該使用GCD同步隊列(dispatch_sync)來實現代碼的關鍵部分。 一個例子是從帳戶余額中減去交易金額的塊。 同步調用的有趣部分是一個問題,它如何影響多個線程上其他塊的工作?

讓我們假設有3個線程在異步模式下使用和執行主隊列和自定義隊列中的系統和用戶定義塊的情況。 這些塊都以某種順序並行執行。 現在,如果將塊放在具有同步模式的自定義隊列上,這是否意味着所有其他塊(包括在其他線程上)都被掛起,直到塊成功執行為止? 或者這是否意味着只有一些鎖定將被放置在該塊上,而其他鎖定仍將執行。 但是,如果其他塊使用與同步塊相同的數據,那么其他塊將不可避免地等到該鎖將被釋放。

恕我直言無所謂,是一個還是多個核心,同步模式應該凍結整個應用程序的工作。 但是,這些只是我的想法所以請評論並分享您的見解:)

同步調度會暫停代碼的執行,直到調度塊完成。 異步調度立即返回,該塊與調用代碼異步執行:

dispatch_sync(somewhere, ^{ something });
// Reached later, when the block is finished.

dispatch_async(somewhere, ^{ something });
// Reached immediately. The block might be waiting
// to be executed, executing or already finished.

並且有兩種調度隊列,串行和並發。 串行的按照添加順序嚴格逐個發送塊。 當一個完成時,另一個開始。 這種執行只需要一個線程。 並發隊列並行地同時調度塊。 那里使用了更多的線程。

您可以根據需要混合和匹配同步/異步調度和串行/並發隊列。 如果要使用GCD來保護對關鍵部分的訪問,請使用單個串行隊列並對此隊列上的共享數據執行所有操作(同步或異步,無關緊要)。 這樣,只有一個塊與共享數據一起運行:

- (void) addFoo: (id) foo {
    dispatch_sync(guardingQueue, ^{ [sharedFooArray addObject:foo]; });
}

- (void) removeFoo: (id) foo {
    dispatch_sync(guardingQueue, ^{ [sharedFooArray removeObject:foo]; });
}

現在,如果guardingQueue是一個串行隊列,即使從不同的線程同時調用addFoo:removeFoo:方法,添加/刪除操作也永遠不會發生沖突。

不,不。

同步部分是將塊放在隊列中,但是在塊返回之前,控制不會傳遞回調用函數。

GCD的許多用途都是異步的; 你把一個塊放在隊列上而不是等待塊完成它的工作控制被傳遞回調用函數。

這對其他隊列沒有影響。

如果您需要序列化對某個資源的訪問權限,那么至少有兩種機制可供您訪問。 如果您有一個帳戶對象(對於給定的帳號是唯一的),那么您可以執行以下操作:

@synchronize(accountObject) { ... }

如果您沒有對象但使用的C結構對於給定的帳號只有一個這樣的結構,那么您可以執行以下操作:

// Should be added to the account structure. 
// 1 => at most 1 object can access accountLock at a time.
dispatch_semaphore_t accountLock = dispatch_semaphore_create(1);

// In your block you do the following:
block = ^(void) {
    dispatch_semaphore_wait(accountLock,DISPATCH_TIME_FOREVER);
    // Do something
    dispatch_semaphore_signal(accountLock);
};

// -- Edited: semaphore was leaking.
// At the appropriate time release the lock
// If the semaphore was created in the init then 
// the semaphore should be released in the release method.
dispatch_release(accountLock);

這樣,無論隊列的並發級別如何,都可以保證在任何給定時間只有一個線程可以訪問帳戶。

還有更多類型的同步對象,但這兩種對象易於使用且非常靈活。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM