Блокировка не снимается для других потоков

1

У меня есть 5 потоков, которые пытаются ввести критический раздел статического класса в произвольное время. Если другой поток находится в критическом разделе, я хочу, чтобы остальные "отступили" и попытались в более позднее время. Проблема заключается в том, что кажется, что блокировка не освобождается после того, как первый поток входит в критический раздел, потому что остальные false всегда будут возвращены, если "точка останова" в Monitor.TryEnter(thisLock). Любая помощь будет оценена по достоинству. Благодарю.

Это мой код:

static class Receiver
    {
        public static object thisLock = new object();
        public static int success;

        public static bool hasLocked()
        {
            if(Monitor.TryEnter(thisLock))
            {
                Monitor.Enter(thisLock);
                System.Threading.Thread.Sleep(10);
                success++;
                Monitor.Exit(thisLock);
                return true;
            }
            return false;
        }
    }
  • 2
    Вы Monitor.TryEnter(thisLock) блокировку дважды Monitor.TryEnter(thisLock) затем снова Monitor.Enter(thisLock) , но Monitor.Enter(thisLock) только один раз.
  • 0
    Спасибо за вашу помощь.
Теги:
multithreading

2 ответа

3
Лучший ответ

Легально, чтобы тот же поток вызывал Enter более одного раза без его блокировки; однако необходимо вызывать равное количество вызовов выхода, прежде чем другие потоки, ожидающие на объекте, будут разблокированы.

http://msdn.microsoft.com/en-us/library/de0542zz%28v=vs.110%29.aspx

В принципе, вы приобретаете блокировку два раза в своем коде. Вам необходимо удалить вызов Monitor.Enter так как Monitor.TryEnter уже приобрел блокировку.

static class Receiver
{
    public static object thisLock = new object();
    public static int success;

    public static bool hasLocked()
    {
        if(Monitor.TryEnter(thisLock))
        {
            System.Threading.Thread.Sleep(10);
            success++;
            Monitor.Exit(thisLock);

            return true;
        }

        return false;
    }
}
  • 0
    Большое спасибо за вашу помощь, это было упущением с моей стороны.
2

Вы приобретаете блокировки дважды, но только один раз отпускаете его.

Если TryEnter успешным, вы получите блокировку. Это означает, что вам не нужно явно получать его снова. Однако вам нужно его явно освободить. Таким образом, ваш код должен выглядеть так:

static class Receiver
    {
        public static object thisLock = new object();
        public static int success;

        public static bool hasLocked()
        {
            if(Monitor.TryEnter(thisLock))
            {
                System.Threading.Thread.Sleep(10);
                success++;
                Monitor.Exit(thisLock);
                return true;
            }
            return false;
        }
    }

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню