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

Я хочу узнать, заблокирована ли переменная блокировки pthread или нет. Одним из простых подходов является использование блокировки блокировки, как показано ниже.

pthread_mutex_t lockVar;
if(pthread_mutex_trylock(&lockVar) == 0)
{
    //lock was successful
    pthread_mutex_unlock(&lockVar);
}
else
{
    //someone else holds the lock
}

Как сделать то же самое без блокировки?


person arunmoezhi    schedule 05.09.2014    source источник
comment
Я думаю, что слово, которое вы ищете, это мьютекс.   -  person Kerrek SB    schedule 06.09.2014
comment
Это прямо там, в коде ;-)   -  person Mawg says reinstate Monica    schedule 26.01.2017


Ответы (2)


Когда у вас одновременно происходит несколько исполнений, понятия «одновременность» не существует. Событиям нельзя придать глобальный порядок во времени, за исключением случаев явной синхронизации. Нет свойства, которое можно было бы наблюдать изнутри языка, которое могло бы наблюдать какой-либо порядок в целом.

В частности, вопрос «заблокирован ли тот мьютекс» бессмысленен. У него нет ответа, на основании которого вы могли бы действовать. Каким бы ни был фиктивный ответ, состояние мьютекса может измениться сразу после этого. Вы ничего не можете сделать с таким ответом, как «да, он заблокирован» (он может стать разблокированным в то же время) или «нет, он разблокирован» (он может быть заблокирован до того, как вы туда доберетесь).

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

person Kerrek SB    schedule 05.09.2014
comment
Спасибо за объяснение. Whatever the fictitious answer is, the state of the mutex can change right after. Ну и что?. It has no answer upon which you can act. Почему? - person arunmoezhi; 06.09.2014
comment
@arunmoezhi: Единственный способ, которым ответ будет иметь смысл, - это если в вашей программе есть инварианты, такие как невозможность того, чтобы другой поток снова заблокировал мьютекс после его разблокировки. И в таком случае вы можете просто оставить мьютекс заблокированным, как только вы получите его через trylock, поскольку вы не будете блокировать продвижение вперед какого-либо другого потока. - person R.. GitHub STOP HELPING ICE; 06.09.2014
comment
Я думаю, вопрос в том, что заблокированный мьютекс имеет смысл в параллельной настройке, которая ослаблена в том смысле, что частичного порядка достаточно для правильности - person arunmoezhi; 06.09.2014
comment
В любом случае то, как вы это делаете прямо сейчас, является единственно возможным и единственно потенциально-правильным способом. Но вполне вероятно, что ваше желание даже задать этот вопрос ошибочно. - person R.. GitHub STOP HELPING ICE; 06.09.2014
comment
@arunmoezhi: Если вы не можете принять ответ как данность, я думаю, вам нужно объяснить, что вы хотите сделать с ответом, чтобы Керрек или я могли устранить оставшуюся путаницу, которая у вас есть по поводу его ответа. - person R.. GitHub STOP HELPING ICE; 06.09.2014
comment
Я думаю, что его ответ правильный, когда вам нужен полный порядок в качестве критерия правильности. Я должен был упомянуть в вопросе, что я не ищу полного порядка. Это требование, которое у меня есть в параллельном алгоритме, когда значение мьютекса может измениться после того, как я его прочитаю. - person arunmoezhi; 06.09.2014
comment
@arunmoezhi: Дело не в полном порядке. Речь идет о том, существует ли какое-либо свойство. Для того, чтобы существовать, что-то должно иметь возможность что-то изменить. Я могу дать вам bool is_mutex_locked(pthead_mutex_t *) { return true; }, здесь нет никакого способа доказать, что эта функция неверна (без какой-либо другой промежуточной синхронизации). - person Kerrek SB; 06.09.2014
comment
@KerrekSB: Конечно, есть. Если других потоков не существует, функция неверна. Есть много других способов доказать, что это неправильно. На самом деле это интересная тема, потому что многие люди ошибочно думают, что вы не можете доказать, что глючная реализация trylock неверна, но вы можете это сделать. Эта тема возникла во время добавления исключения блокировок в glibc и снова во время согласования POSIX с моделью памяти C11. :-) - person R.. GitHub STOP HELPING ICE; 06.09.2014
comment
@R..: Если ваша программа однопоточная, то у вас тривиально есть точки синхронизации везде, что я пытался исключить в своем аргументе. Да, если вы прикажете, как все происходит, все будет происходить по порядку, без сомнения :-) - person Kerrek SB; 06.09.2014

Независимо от того, что вы хотите сделать с результатом, то, как вы это делаете прямо сейчас, является единственным способом. Вы не можете просто запросить, заблокирован ли мьютекс, не блокируя его. Если вам нужен примитив синхронизации, для которого вы можете запрашивать статус без его изменения, возможно использование семафоров POSIX. Двоичный семафор может служить в качестве блокировки (хотя в нем отсутствует концепция владельца, что может быть проблемой для вас, если вам нужна рекурсивная блокировка), и sem_getvalue может определить, "заблокирован" ли семафор в один момент времени. момент времени.

Что касается того, имеет ли вообще смысл вопрос, который вы задаете, Керрек уже сказал вам, что обычно это не так. Вот несколько возможных, минимально полезных фрагментов информации, которые вы можете получить из отрицательных или положительных результатов:

  • Отрицательный:

    • If you know the lock started out locked, and won't be locked again once it's unlocked, this tells you an operation has finished. Here, a trylock-and-unlock approach would prevent multiple threads from being able to do this, since it would break the "never locked again once it's unlocked" invariant.
    • Может указывать на то, что стоит подготовить данные без удержания блокировки, которые вы можете применить позже с помощью попытки блокировки/разблокировки, удерживаемой только в течение короткого промежутка времени после подготовки данных. Но, конечно, вы должны быть готовы к тому, что к тому моменту, когда вы возьмете замок позже, все изменится.
  • Положительный:

    • If you know that the lock will not be unlocked once it's taken until your thread performs a further action allowing the lock-holder to proceed, this gives you information that a lock-holder has arrived.
  • Может другие...

Но по большей части «заблокирован ли мьютекс?» не полезный вопрос.

person R.. GitHub STOP HELPING ICE    schedule 05.09.2014
comment
Дело в том, что, скажем, ваша первая точка, операция завершена, заключается в том, что вы не можете полагаться исключительно на эту технику, так как вы можете никогда не увидеть завершение таким образом. Поэтому вам уже придется написать отдельный путь кода для обработки общего случая. В этот момент вы, скорее всего, просто отбросите путь кода специального случая... - person Kerrek SB; 06.09.2014
comment
@KerrekSB: Если вам не нужна синхронизация памяти (например, вам просто нужно упорядочить некоторые операции с файловыми дескрипторами), может быть достаточно только знания о том, что операция завершена, без дополнительной синхронизации. Я согласен, что обычно это неправильно, и я пытался убедить OP в этом, но я подумал, что некоторые примеры ограниченных особых случаев, когда вы можете использовать результат, могут быть информативными, чтобы помочь OP понять, что в большинстве случаев вы не можете. - person R.. GitHub STOP HELPING ICE; 06.09.2014
comment
Извините, я все еще не понимаю вашу точку зрения. Переменная мьютекса начинается с состояния unlocked. Затем он меняется на locked,unlocked,locked... Допустим, если наблюдатель хочет прочитать состояние переменной мьютекса (не обязательно текущее состояние). Допустим, он прочитал значение как locked. Но к тому времени, когда он/она прочитал это, значение могло измениться на unlocked. Но значение, которое он / она прочитал, было некоторым действительным состоянием в прошлом. Если значение, которое он прочитал, НЕ является значением из прошлого или настоящего, тогда у меня проблемы. Но пока это часть истории, я в порядке. - person arunmoezhi; 06.09.2014
comment
@arunmoezhi: Дело в том, что без синхронизации нет истории. Прошлого нет. Прошлое подразумевает временной порядок, но его нет (если вы не синхронизируете). - person Kerrek SB; 06.09.2014
comment
Это дает представление о том, что я пытаюсь спросить. en.wikipedia.org/wiki/ - person arunmoezhi; 06.09.2014
comment
@KerrekSB: возможность чтения состояния определяет какой-то порядок. Это может не быть частью общего заказа на погрузку и хранение, но это все же тип заказа. Например, если несколько вызовов гипотетической функции запроса состояния блокировки вернули значение «разблокировано», «заблокировано», «разблокировано» в указанном порядке, это потенциально могло бы упорядочить их по отношению к операциям блокировки в других потоках. - person R.. GitHub STOP HELPING ICE; 06.09.2014
comment
@R.. Я согласен с вашим комментарием. Это имеет частичный порядок. - person arunmoezhi; 06.09.2014