#multithreading #c -cli #ipc #mutex #deadlock
#многопоточность #c -cli #ipc #мьютекс #взаимоблокировка
Вопрос:
В попытке избавить мой графический интерфейс от условий гонки и взаимоблокировок у меня есть следующая функция, которую я вызываю из c’torи всякий раз, когда мне нужна служба, которая разделяет мое имя mutex
, чтобы предоставить его ввод:
void EnvCapt::FireServiceAndOrHold() {
try {
mutTimerSyncEx->ReleaseMutex();
Thread::Sleep(100); //Time enough for the service to complete.
if (!mutTimerSyncEx->WaitOne(3 * int_ms)) {//int_ms = the polling period
//Must've been doubly locked or worse.
mutTimerSyncEx->ReleaseMutex();
FireServiceAndOrHold();
}
} catch (Exception ^ ex) {
//Released unheld mutex. Retake control.
mutTimerSyncEx->WaitOne();
FireServiceAndOrHold();
}
}
Это работает относительно хорошо, но я вызываю это, прежде чем разрешить службе, теперь я готов принять ввод, поэтому он никогда не пытается ждать, пока я выпущу для него мьютекс. Прежде чем я попытаюсь изменить порядок вещей, я хотел бы знать, что происходит не так с вышеупомянутой функцией. Ошибка, которую я получаю,:
Метод синхронизации объекта был вызван из несинхронизированного блока кода.
Поскольку вызов release для a mutex
, который не был WaitOne
‘d, приведет к сбою, я поймаю это, зная, что я могу взять на себя ответственность за это и продолжить. Но я ошибаюсь. Он навсегда зависает в WaitOne()
инструкции. Я знаю, что делает другой процесс все это время, потому что он заблокирован в моем втором окне отладчика. Это не касается мьютекса.
Обновить
Я попытался изменить порядок, который я сначала предложил, это показалось хорошим, но теперь я обнаружил, что мьютекс является только глобальным, несмотря на наличие глобального name .
-
Он является общим, потому что, когда мой графический интерфейс c’tor’s
firstInstance
имеет значение false, поэтому я пытаюсь взять его под контроль. -
Он не является общим, потому что, когда графический интерфейс вызывает
WaitOne()
его, графический интерфейс блокируется на неопределенный срок. В то время как служба танцует прямо через свой вызовWaitOne()
, не заботясь ни о чем в мире.
Комментарии:
1. почему вы используете примитивы синхронизации и повторяете предположение («должно быть, была двойная блокировка …» и «зная, что я могу взять на себя ответственность за это и продолжить» -> это так не работает. Вы НИКОГДА не сможете узнать, что «вы можете стать владельцем», если вы не держите мьютекс заблокированным . Остальное — это просто «улучшенное» условие гонки (возможно, мьютекс был заблокирован, когда вы получили исключение). Кроме того, исключения предназначены для исключительных ситуаций.
2. Если я выпускаю общий именованный мьютекс, и он выдает, это может означать только то, что он не заблокирован. Поэтому я могу взять на себя ответственность. В некоторых ситуациях исключения происходят постоянно и должны быть устранены, если это единственный способ решить проблему. Пожалуйста, это относится к .NET, а не к C -CLI, перевод минимален, когда мы имеем дело с такими высокоуровневыми концепциями, как мьютекс и синхронизация. Или, что угодно, просто верните моему коду его цвет!
3. нет. Вы только что определили условие гонки. Возможно, он был заблокирован в то же время. Кроме того, нет абсолютно никакой необходимости перехватывать исключение при освобождении мьютекса, который вы не удерживаете, потому что вы всегда можете узнать, удерживали ли вы его уже. Это то, что я имел в виду, говоря «исключения для исключительных ситуаций».
4. Нет, не заблокирован ничем, чего я не вижу. У меня есть отладчик для потоков обоих процессов, практически в каждой строке есть точки останова.
5. Условие гонки, которое описывает sehe, — это когда вы проверили статус блокировки, а затем попытались ее принять. Между этими двумя действиями другой поток, возможно, уже предпринял его. То, что вы знаете, что другой поток в данный момент этого не делал, не означает, что это невозможно при дальнейших исполнениях.
Ответ №1:
У меня просто возникла идея, что может быть не так у вас там:
Подсказка: вы не можете освободить мьютекс от имени другого процесса! Другой процесс должен будет освободить мьютекс, если он его удерживает:
Process 1: Process 2:
============ =============
WaitOne (locks the mutex)
// do work WaitOne (awaits the mutex)
// do more work
// done
ReleaseMutex ------> WaitOne returns from the wait _with
the mutex locked_
Комментарии:
1. Я могу выпустить общий мьютекс с глобальным именем от имени другого процесса, иначе какой смысл делиться? Они не будут синхронизироваться. Хм, я вижу, где я, возможно, нарушил его. Возможно, до сих пор все они снимали свои собственные блокировки, но это не похоже на совместное использование, если у каждого есть отдельные блокировки. Не думаю, что у меня есть время проверить это сегодня вечером. Можете ли вы сослаться на некоторые доказательства того, что вы описываете?
2. @John: какой смысл удерживать блокировку, если другой процесс может освободить ее от вашего имени ? Пожалуйста, сначала ознакомьтесь с примитивами синхронизации. редактировать : я думаю, вы хотите назвать события
3. Что касается доказательств: ваш вопрос, похоже, несет его. Редактировать Теперь я вижу вашу правку. Успокойтесь, удачи в поиске ошибок завтра!
4. Вы определенно не можете освободить ресурсы, которые вам не принадлежат. Какой смысл что-то блокировать, если кто-то другой может просто снять вашу блокировку в середине того, что вы делали?
5. Черт возьми, я просто добавляю новые условия гонки со всеми моими точками останова. Так много для моей системы реального времени. Спасибо, ребята. Извините, если я причинил какое-либо оскорбление, на этой неделе было несколько поздних ночей, и я продрог до костей. Приятно, вопрос в качестве доказательства 1