我了解到信號量可以充當原子鎖,它可以執行兩個功能:down
和up
。
有什么辦法可以value
原子地交換兩個指標,避免競爭條件和死鎖。
我首先想出了“解決方案”,假設兩個指標都有:
Item a = { value = "A", lock = Semaphore(1) }
Item b = { value = "B", lock = Semaphore(1) }
void atomic_swap(Item* a, Item* b) {
a->lock.down(); // acquire
b->lock.down(); // acquire
non_atomic_swap(&a.value, &b.value);
b->lock.up(); // release
a->lock.up(); // release
}
但是如果我沒記錯的話,如果atomic_swap
使用相同的指標呼叫兩個,則會導致死鎖:例如。
Item a = ...;
Item b = ...;
thread_start(atomic_swap, {&a, &b}); // start a thread running atomic_swap(&a, &b);
thread_start(atomic_swap, {&b, &a}); // start a thread running atomic_swap(&b, &a);
在上面的代碼中,如果兩個呼叫同時atomic_swap
到達第一個down
,下一個down
將永遠阻塞,從而導致死鎖。
我可以考慮避免死鎖的解決方案之一是為它們分配一個“組”,只有同一組中的專案可以atomic_swap
安全地執行(沒有死鎖):
Group g = { lock = Semaphore(1) };
Item a = { value = "A", group = g };
Item b = { value = "B", group = g };
void atomic_swap(Item* a, Item* b) {
// assume a->group == b->group
a->group.down() // b->group.down()
non_atomic_swap(&a.value, &b.value);
a->group.up(); // b->group.up();
}
但這當然要求每個專案都攜帶一個group
,并且不相關的專案可能會因為其他呼叫而等待該組。
有沒有什么好的方法來執行atomic_swap
理論上使用信號量?
uj5u.com熱心網友回復:
您可以使用std::less
比較指標以確保所有用戶以相同的順序獲取鎖:
void atomic_swap(Item* a, Item* b) {
std::less<Item *> cmp;
if (cmp(a, b)) {
a->lock.down();
b->lock.down();
} else {
b->lock.down();
a->lock.down(); }
non_atomic_swap(&a->value, &b->value);
b->lock.up(); // release
a->lock.up(); // release
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/450267.html
下一篇:System.Threading.TimersTimerCallback事件處理程式中捕獲的例外,然后重新拋出未發送回主執行緒