Что происходит, когда два потока ПОПЫТАЮТСЯ заблокировать один и тот же ресурс в одно и то же время?

Что происходит, когда два потока пытаются заблокировать один и тот же объект в одну и ту же микросекунду (или в любое другое время, которое является наименьшим промежутком времени, в течение которого может быть измерен срез ЦП или инструкция)?

Возможно ли, чтобы два потока выполняли инструкции одновременно в одно и то же время, или это невозможно с современным оборудованием?

Я работаю над проектом, который касается многопоточности, где любой поток может, так сказать, опередить другой до финиша. Поэтому, естественно, вопрос «Что происходит, когда все они блокируются одновременно?» нужно решать ИМО.


person Martin Bliss    schedule 28.07.2012    source источник
comment
попробуйте прочитать это albahari.com/threading/part2.aspx   -  person Diego De Vita    schedule 28.07.2012
comment
«Что происходит, когда они все запираются одновременно?» Это невозможно по определению. Если что-то подобное может случиться, это не замок.   -  person Martin James    schedule 28.07.2012
comment
может быть, другой способ поставить вопрос: как ведет себя блокировка, когда несколько потоков достигают этой точки? хорошо, я предполагаю, что внутренняя работа поставит в очередь доступ к этому ресурсу, и единственный сценарий отказа будет, когда вы задействуете несколько последовательных доступов к разным ресурсам и попадете в так называемую тупиковую ситуацию. В любом случае смысл блокировки в том, чтобы позволить завершить полный блок кода до того, как ресурс будет высвобожден для кого-то другого. В противном случае вы не предоставлены, и ваша логика может дать сбой   -  person Diego De Vita    schedule 28.07.2012
comment
Диего Де Вита правильно истолковал мой вопрос. Следует переформулировать. Что происходит, когда два потока ПОПЫТАЮТСЯ заблокировать один и тот же ресурс?   -  person Martin Bliss    schedule 28.07.2012
comment
@MartinBliss - только один добьется успеха. Другой либо получит немедленный возврат ошибки, либо ему будет отказано в выполнении до тех пор, пока блокировка не будет освобождена потоком, которому удалось получить блокировку (или, иногда, до тех пор, пока не пройдет интервал времени ожидания без получения блокировки, что приведет к тайм-ауту). -неудачный возврат).   -  person Martin James    schedule 28.07.2012
comment
@MartinJames Кажется, это противоречит ответу sblom ниже. Звучит так, как будто вы отвечаете на вопрос Как работает блокировка? а не то, что происходит, когда два потока пытаются заблокировать один и тот же ресурс в один и тот же момент.   -  person Martin Bliss    schedule 28.07.2012
comment
Во всяком случае, я не противоречу ответу @sblom. Межпроцессорные блокировки требуют аппаратной поддержки, детали которой зависят от архитектуры.   -  person Martin James    schedule 29.07.2012


Ответы (2)


Современные блокировки практически во всех средах спроектированы таким образом, что два потока не могут заблокировать объект одновременно. В современных процессорах возможно два потока, выполняющиеся на двух разных ядрах, пытаются получить блокировку практически одновременно, но все они реализуют механизмы синхронизации, которые позволяют программному обеспечению запрещать это. .

Например, x86-64 имеет МОНИТОР и MWAIT. По сути, они реализуют на уровне микропроцессора семантику .NET lock(){}, System.Threading.Monitor.Wait() и System.Threading.Monitor.Enter()/.Exit().

person sblom    schedule 28.07.2012
comment
да, но в среде .net речь идет о языковом домене и о том, как будет вести себя среда выполнения в таком сценарии. Мой ответ: если вы не заблокируете общие ресурсы, их доступ не будет потокобезопасным, и ваша логика может быть полностью испорчена. - person Diego De Vita; 28.07.2012
comment
Мне нравится ответ сблума. Я полагал, что компьютерное оборудование должно иметь какие-то механизмы синхронизации инструкций, но я хотел быть уверенным, прежде чем делать такое предположение... Спасибо, сблом! - person Martin Bliss; 28.07.2012

Это невозможно, замки не могут делать то, что обещают. Для этого требуется поддержка процессора, поскольку только он может гарантировать, что несколько ядер не будут пытаться получить доступ к одной и той же ячейке памяти одновременно. Примером может служить фрагмент ассемблерного кода, используемый версией CLR x86 в методе Monitor.TryEnter():

FASTCALL_FUNC CompareExchangeUP,12
        _ASSERT_ALIGNED_4_X86 ecx
        mov     eax, [esp+4]    ; Comparand
        cmpxchg [ecx], edx
        retn    4               ; result in EAX
FASTCALL_ENDFUNC CompareExchangeUP

Инструкция процессора cmpxchg обеспечивает гарантию атомарности. Это инструкция, которая есть в любом современном ядре, ее общее название - «сравнить и поменять местами». Подробнее об этой инструкции вы найдете в этой статье Википедии.

person Hans Passant    schedule 28.07.2012