Это простое расширение классического тупика для случая, когда одна из блокировок предоставляется компилятором.
void A2B() { a.Lock(); B(); a.Unlock(); }
void B() { b.Lock(); ...; b.Unlock(); }
void B2A() { b.Lock(); A(); b.Unlock(); }
void A() { a.Lock(); ...; a.Unlock(); }
Классическая тупиковая ситуация возникает, если один поток вызывает A2B()
, а другой поток вызывает B2A()
.
В статической блокировке инициализации компилятор обеспечивает блокировку b
.
int A() { a.Lock(); ...; a.Unlock(); return 0; }
void B2A() { static int v = A(); }
void A2B() { a.Lock(); B2A(); a.Unlock(); }
Если вы предполагаете блокировку статической инициализации, тогда код тайно преобразуется в
void B2A() {
if (!initialized) {
b.Lock(); // standard double-check-lock
if (!initialized) v = A();
initialized=true;
b.Unlock();
}
}
Один поток вызывает A2B()
, а другой - B2A()
.