Взаимная блокировка, активная блокировка, голодание блокировки в параллельном программировании

интервью

тупик

Взаимная блокировка — это явление, при котором два или более процессов (потоков) блокируются из-за конкуренции за ресурсы или связи друг с другом в процессе выполнения, без внешней силы они не смогут продвигаться вперед. В это время говорят, что система находится в состоянии взаимоблокировки или в системе есть взаимоблокировка.Эти процессы (потоки), которые всегда ждут друг друга, называются процессами взаимоблокировки (потоками).

Четыре необходимых условия возникновения взаимоблокировки

  • Условие взаимного исключения: потоки (процессы) являются эксклюзивными для выделенных ресурсов, то есть ресурс может быть занят только одним потоком (процессом), пока он не будет освобожден потоком (процессом).
  • Условия запроса и удержания: когда поток (процесс) блокируется из-за запроса на занятые ресурсы, он будет удерживать полученные ресурсы.
  • Условие отсутствия лишения: ресурсы, полученные потоком (процессом), не могут быть принудительно лишены другими потоками до того, как они будут израсходованы, и ресурсы освобождаются только после того, как они будут израсходованы.
  • Циклическое условие ожидания: при возникновении взаимоблокировки ожидающий поток (процесс) должен сформировать цикл (аналогичный бесконечному циклу), что приводит к постоянной блокировке.

Как обнаружить

Используйте jstack или jconsole для просмотра стеков потоков.

"Thread-1" prio=10 tid=0x00007fe8c00a0800 nid=0x17cc waiting for monitor entry [0x00007fe8c5031000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at DeadLocakTest$DeadThread2.run(DeadLocakTest.java:61)
        - waiting to lock <0x00000000af24b248> (a java.lang.Object)
        - locked <0x00000000af24b258> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:745)
 
   Locked ownable synchronizers:
        - None
 
"Thread-0" prio=10 tid=0x00007fe8c009e800 nid=0x17cb waiting for monitor entry [0x00007fe8c5132000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at DeadLocakTest$DeadThread1.run(DeadLocakTest.java:38)
        - waiting to lock <0x00000000af24b258> (a java.lang.Object)
        - locked <0x00000000af24b248> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:745)
 
   Locked ownable synchronizers:
        - None

Thread-1

locked <0x00000000af24b258>
waiting to lock 0x00000000af24b248

Thread-0

locked 0x00000000af24b248
waiting to lock 0x00000000af24b258

Как решить

  • Прерывание запроса и удержание: Запрос всех ресурсов одновременно.
  • Уничтожение условия отказа от вытеснения: когда поток, занимающий некоторые ресурсы, в дальнейшем обращается за другими ресурсами, если он не может подать заявку на них, он может активно освобождать ресурсы, которые он занимает.
  • Разрушьте циклическое условие ожидания: подавайте заявки на ресурсы по порядку и освобождайте ресурсы в обратном порядке.

живой замок

Livelock означает, что задача или исполнитель не заблокированы, потому что не выполняются какие-то условия, в результате чего повторяются попытки, сбои, попытки, сбои. Разница между livelock и deadlock заключается в том, что сущность в livelock постоянно меняет состояние, так называемое «живое», в то время как сущность в deadlock находится в ожидании; livelock может сняться сам по себе, а deadlock — нет.

Для разрешения живых блокировок может быть введена некоторая случайность, например, при обнаружении конфликта приостановка на случайный период времени и повторная попытка. Это время значительно снижает вероятность столкновения. Типичным примером является механизм обнаружения CSMA/CD Ethernet.

блокировка голодания

Голодание: это означает, что если поток T1 занимает ресурс R, поток T2 снова запрашивает блокировку R, поэтому T2 ждет. Т3 также запрашивает ресурс R. Когда Т1 снимает блокировку с R, система сначала одобряет запрос Т3, а Т2 все еще ждет. Затем T4 снова запрашивает блокировку R. Когда T3 снимает блокировку с R, система снова одобряет запрос T4... и T2 может ждать вечно.