Замки не истекают . Когда поток пытается передать оператор lock
, он может сделать это только в том случае, если никакой другой поток не выполняется внутри блока lock
, имеющего блокировку для этого конкретного экземпляра объекта, используемого в элементе состояния lock
.
В вашем случае кажется, что у вас выполняется основной поток. Он заблокирует как экземпляры status
, так и clients
, прежде чем будут запущены новые задачи, выполняемые в отдельных потоках. Если какой-либо код в новых потоках хочет получить блокировку либо на status
, либо на clients
, ему придется подождать, пока основной поток освободит обе блокировки, оставив оба блока lock
. Это происходит, когда remoteAction_JobStatusUpdated
возвращается.
Вы передаете объект status
каждому рабочему потоку, и они все могут делать с этим объектом все, что хотят. Оператор lock (status)
никоим образом не защищает экземпляр status
. Однако если какой-либо из потоков попытается выполнить lock (status)
, он будет блокироваться, пока основной поток не снимет блокировку.
Использование двух отдельных экземпляров объекта для блокировки может привести к тупику. Предположим, что один поток выполняет следующий код:
lock (status) {
...
lock (clients) {
...
}
}
Другой поток выполняет следующий код, где блокировки получаются в обратной последовательности:
lock (clients) {
...
lock (status) {
...
}
}
Если первому потоку удается сначала получить статус, а второму клиенты сначала блокируют, они блокируются, и оба потока больше не работают.
В общем, я бы посоветовал вам инкапсулировать ваше общее состояние в отдельный класс и сделать доступ к нему потокобезопасным:
class State {
readonly Object locker = new Object();
public void ModifyState() {
lock (this.locker) {
...
}
}
public String AccessState() {
lock (this.locker) {
...
return ...
}
}
}
Вы также можете пометить ваши методы с помощью атрибута [MethodImpl (MethodImpl.Synchronized)] * , но у него есть свои подводные камни, так как он будет окружать метод lock (this)
, что в общем случае не рекомендуется .
Если вы хотите лучше понять, что происходит за кулисами оператора lock
, вы можете прочитать статью Безопасная синхронизация потоков в журнале MSDN.