我正在使用GCD爲類添加線程安全性。使用GCD和代碼重用:避免可重入代碼死鎖
我班的一些公共方法被其他公共方法調用。但是,這會導致重入鎖定問題:如果我使用同步GCD塊(在某些情況下)保護適當的公開可見方法,則重用意味着有時我會嘗試在當前隊列上運行另一個同步塊,這會導致死鎖。
什麼是最優雅的解決方案?一個顯而易見的方法是使用適當方法的內部版本,沒有任何GCD塊,以及具有GCD塊的外部公開版本的方法將調用包裝到interal方法中。這不太適合我。
我正在使用GCD爲類添加線程安全性。使用GCD和代碼重用:避免可重入代碼死鎖
我班的一些公共方法被其他公共方法調用。但是,這會導致重入鎖定問題:如果我使用同步GCD塊(在某些情況下)保護適當的公開可見方法,則重用意味着有時我會嘗試在當前隊列上運行另一個同步塊,這會導致死鎖。
什麼是最優雅的解決方案?一個顯而易見的方法是使用適當方法的內部版本,沒有任何GCD塊,以及具有GCD塊的外部公開版本的方法將調用包裝到interal方法中。這不太適合我。
這裏有幾個想法:
看看你能不能用一成不變的對象。這意味着無論何時一個方法會修改對象,它實際上會返回一個新的對象,並具有修改後的狀態。塊將繼續並使用這個新的對象。這很簡單,不需要特別照顧,但並非總是可行。
看看你的公共方法不能使用私有方法,攜帶狀態。由於每個塊都會帶有自己的內部狀態,所以你也是線程安全的。
如果你有一些實例的使用情況下,它可能會導致更多的想法...
我已經在我們的C++使用調度隊列同步類使用這樣的模式非常成功:
class Foo
{
public:
void doSomething() {
dispatch_sync(fQueue, ^{ doSomething_sync(); });
}
private:
void doSomething_sync() { ... }
private:
dispatch_queue_t fQueue;
};
這裏的一般慣例是,在一類任一給定_sync
方法,你只能調用其他方法_sync
而不是他們的非公開_sync
對口。
只要你的類不需要對隊列中運行的外部代碼進行任何回調,你的「顯而易見的方法」就非常好。在這種情況下,外部代碼可能會調用另一個公共方法並導致死鎖。 – 2013-03-15 22:45:30
還有另一個更微妙的問題,就是它可以防止子類覆蓋事物(因爲它們的覆蓋不會被調用,因爲它們不是內部版本)。如果這不是問題,這是做到這一點的最佳方式。如果這是一個問題,你需要(呃)遞歸鎖定,並且不能使用GCD。 – 2013-03-16 01:11:02