C # Многопоточность проблема с Monitor-class - возможен ли блокировка жизни? - PullRequest
1 голос
/ 13 марта 2009

У меня есть немного кода, который я не могу понять правильно. Проблема в том, что программа многопоточная, и внутри есть немного кода, который нужно синхронизировать, поэтому я написал это:

lock (lockObject)
{
   if (!Monitor.TryEnter(lockObject))
     Monitor.Wait(lockObject);

   //do stuff...
   Monitor.PulseAll(lockObject);
}
Monitor.Exit(lockObject);

Проблема, с которой я столкнулся, заключается в том, что в какой-то момент все потоки кажутся спящими - может кто-нибудь сказать, почему? Программа продолжает работать бесконечно, почти не потребляя процессор, но никакой работы не делается - при трассировке программы я обнаружил, что в какой-то момент ни один поток не активен, но многие из них не работают Я знаю, что ошибка в основном (в случае разработчика - всегда) находится на 0,5 м перед монитором - но я не могу разобраться сам ... возможно, через несколько минут;)

Может кто-нибудь, пожалуйста, объясните мне это - заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 13 марта 2009

Я предполагаю, что первый оператор блокировки является опечаткой, а вы имели в виду блокировку (lockObject) (строчные буквы).

Я думаю, что вы здесь неправильно понимаете блокировки. Блок if в вашем коде никогда не будет истинным. Причина в том, что блокировка (lockObject) фактически расширяется до следующего

Monitor.Enter(lockObject);
try {
...
} finally{ 
Monitor.Exit(lockObject);

Таким образом, к тому времени, когда вы нажмете на блок if, у вас уже есть блокировка, и TryEnter всегда будет успешным.

1 голос
/ 13 марта 2009

Это странная установка. «LockObject» - это то же самое, что и «LockObject»? Или это опечатка? Если они совпадают, то ваша установка избыточна, так как нет необходимости вызывать Monitor.TryEnter для чего-то, что вы уже блокируете. Если 'LockObject' - это другой объект, то почему бы не переместить Monitor.Exit внутрь оператора блокировки?

1 голос
/ 13 марта 2009

Есть ли разница между LockObject и lockObject? Непонятно ...

Тем не менее! Если это разные объекты, то сначала: вы не можете Wait на блокировке, которой у вас нет ... и TryEnter вернет false только если вы укажете время ожидания. Что именно этот код пытается сделать?

Без дополнительного контекста не совсем понятно, для чего предназначены PulseAll и Wait; например, здесь они используются для блокировки очереди, когда она переполнена (Wait), или освобождают ее, когда становится доступным пространство (PulseAll) и т. д. Трудно отладить код потоков без полного взаимодействия между потоками.

Похоже, вам может понадобиться:

lock (lockObject)
{
    // do stuff
}

Есть две непосредственные проблемы, которые я вижу; Во-первых, не очевидно, что вы всегда снимаете блокировки, которые вы берете (т.е. исключения). Попробуйте просто использовать lock для Enter/Exit - все получится правильно.

Во-вторых, если все темы вызывают Wait ... кто их разбудит? Чего они ждут для ? Как представлено: да, они все будут спать бесконечно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...