Ось, що я намагаюся зробити з Java:
while(writeSetsIntersect()) {
wait();
}
doStuff
notifyAll();
Ось де я застряг: doStuff
може виконуватися одночасно, якщо два потоки записують у різні змінні, тобто вони мають неперервні набори записів. Якщо набори запису перетинаються, потоки повинні чергуватися. Тому я не можу просто сказати doStuff
в синхронізованому блоці, оскільки це не завжди (і може ніколи не бути) необхідним.
Я міг зафіксувати елементи в наборі запису, але якщо два потоки з перетинаючимися наборами записів чекають на одному і тому ж блокуванні, може статися тупик. Як от:
Lock[] locks = new Lock[allAvailableVariables.length];
public void getLocks() {
for(i = 0; i < allAvailableVariables.length; i++)
if(i is in writeSet)
locks[i].lock();
}
Найпростіший спосіб уникнути цього (наскільки я можупридумати) - це синхронізувати придбання замків у вашому наборі записів. Але, якщо два потоки з набором записів, що перетинаються, змагаються, щоб потрапити в блок синхронізації, потоку з набором запису, що не перетинається з двома іншими, доведеться зачекати, поки вони не покинуть блок синхронізації.
Я думаю, я міг би просто мати фіксацію віджиму, але я хотів би уникнути цього, якщо це можливо, оскільки оцінка того, чи перетинаються набори запису, може бути дорогою.
Це взагалі має сенс?
Відповіді:
3 для відповіді № 1Схоже, ви хочете скористатися замовленням замків.
Відсортуйте замки в якомусь природному порядку. Потім зафіксуйте кожен по черзі.
Припустимо, у вас є замки a
і b
з a < b
. Якщо два потоки хочуть зафіксувати обидва a
і b
, вони обидва заблокуються a
спочатку. Тож у вас не може виникнути ситуація, коли нитка заблокувалась b
і заблоковано a
, в той час як інший потік заблоковано a
заблоковано b
.