是的,鎖定層次結構可以有效地防止死鎖;當然,你是否可以真正爲你的程序定義一個層次結構(特別是在存在插件的情況下)完全是另一回事。
基本塊是簡單:
- 每個互斥應該有一個電平(或在編譯時決定或運行時)
- 每個線程應該永遠只獲取以升序互斥或降序級別(決定一次)
我希望我能做正義的想法,請考慮一下草圖下的例子實現;它從未被編譯/測試過。
基本互斥:
template <typename Mutex, size_t Level>
class HierarchicalMutex {
public:
friend class LevelManager;
void lock() {
LevelManager::Lock(*this);
}
void unlock() {
LevelManager::Unlock(*this);
}
private:
size_t previous;
Mutex mutex;
}; // class HierarchicalMutex
template <typename Mutex, size_t Level>
size_t level(HierarchicalMutex<Mutex,Level> const&) { return Level; }
的LevelManager
的作用僅僅是爲了確保電平轉換以正確的順序發生。
class LevelManager {
public:
//
// Single Mutex locking
//
template <typename M>
static void Lock(M& m) {
m.previous = LevelUp(level(m));
m.mutex.lock();
}
template <typename M>
static void Unlock(M& m) {
m.mutex.unlock();
LevelDown(level(m), m.previous);
}
//
// Multiple Mutexes Group Locking
//
// Note: those should expose a "size_t level(M const&)" function,
// and calls to lock/unlock should appropriately call
// this manager to raise/lower the current level.
//
// Note: mutexes acquired as a group
// should be released with the same group.
//
template <typename M>
static void Lock(std::array_ref<M*> mutexes) { // I wish this type existed
using std::begin; using std::end;
auto begin = begin(mutexes);
auto end = end(mutexes);
end = std::remove_if(begin, end, [](M const* m) { return m == 0; });
if (begin == end) { return; }
Sort(begin, end);
size_t const previous = LevelUp(level(*std::prev(end)));
for (; begin != end; ++begin) {
begin->previous = previous;
begin->mutex.lock();
}
}
template <typename M>
static void Unlock(std::array_ref<M*> mutexes) {
using std::begin; using std::end;
auto begin = begin(mutexes);
auto end = end(mutexes);
end = std::remove_if(begin, end, [](M const* m) { return m == 0; });
if (begin == end) { return; }
Sort(begin, end);
std::reverse(begin, end);
for (auto it = begin; it != end; ++it) { it->mutex.unlock(); }
LevelDown(level(*begin), begin->previous);
}
private:
static __thread size_t CurrentLevel = 0;
template <typename It>
static void Sort(It begin, It end) {
using Ref = typename std::iterator_traits<It>::const_reference;
auto const sorter = [](Ref left, Ref right) {
return std::tie(level(left), left) < std::tie(level(right), right);
};
std::sort(begin, end, sorter);
}
static size_t LevelUp(size_t const to) {
if (CurrentLevel >= to) { throw LockHierarchyViolation(); }
CurrentLevel = to;
}
static void LevelDown(size_t const from, size_t const to) {
if (CurrentLevel != from) { throw LockHierarchyViolation(); }
CurrentLevel = to;
}
}; // class LevelManager
踢,我實現鎖定同一級別的倍數鎖單杆的可能性。
正如我在答覆中說,沒有一個關鍵,避免僵局,當你沒有一個簡單的包紮得到它了。最好避免在設計過程中使用它。你的特殊情況是什麼? – 2011-03-17 15:20:58
@Platinum Azure:我正在尋找解決舊代碼和大代碼中的死鎖問題的解決方案。 – StackedCrooked 2011-03-17 15:24:40
我什麼也沒有,對不起。 :-( – 2011-03-17 16:09:27