2010-04-21 2 views
0

Я создал класс «Менеджер», который содержит ограниченный набор ресурсов. Ресурсы хранятся в «Менеджере» как очередь. Я инициализирую Queue и Semaphore одинаковым размером, используя семафор, чтобы заблокировать поток, если ресурсов нет. У меня есть несколько потоков, вызывающих этот класс для запроса ресурса. Вот код псевдео:Состояние семафорской гонки?

public IResource RequestResource() 
{ 
    IResource resource = null; 
    _semaphore.WaitOne(); 

    lock (_syncLock) 
    { 
     resource = _resources.Dequeue(); 
    } 
    return resource; 
} 
public void ReleaseResource(IResource resource) 
{ 
    lock (_syncLock) 
    { 
     _resources.Enqueue(resource); 
    } 
    _semaphore.Release(); 
} 

При запуске этого приложения кажется, что он работает нормально. Тогда, похоже, моя очередь выделяет один и тот же объект. Кажется ли это возможным? Я вытягиваю свои волосы здесь, и любая помощь будет очень признательна. Не стесняйтесь запрашивать дополнительную информацию, если вам это нужно. Благодаря!

+1

Можете вы переформатировать и дать нам код, который вызывает это? –

+0

да, извините, я вставлял в вкладки и думал, что это выглядит правильно в первоначальном предварительном просмотре, исправлено сейчас. – poindexter12

+0

Изменяется ли размер очереди, когда это происходит? Является ли объект одинаковым даже для разных потоков? Каковы шаблоны вызова? Были ли в Enqueue и Dequeue какие-то исключения (у вас там есть ошибки)? Вы пытались отладить его? – 2010-04-21 04:18:13

ответ

2

Семафор действительно случайный здесь; что ограничивает количество потребителей, которые могут приобретать ресурсы одновременно. Синхронизация на самом деле происходит из инструкции lock (критический раздел).

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

Если то, что вы имеете в виду, что метод RequestResource вернули ресурсы, которые уже были приобретены, но не выпустили, есть только три возможные причины, по которым я могу думать:

  1. Очереди содержат дублирующиеся ресурсы из начало;

  2. Потребитель назвал метод Release дважды. В вашем методе Release вы фактически не проверяете, находится ли ресурс уже в очереди; вы можете захотеть изменить этот код, чтобы проверить это и выбросить исключение, которое поможет вам поймать, где дублируются вызовы Release (если это так).

  3. Другой код доступа к _resources очереди без lock.

Мое подозрение было бы # 2, если это действительно то, что вы подразумеваете под дубликатами.

+0

im пытается номер 2 теперь, дайте знать результаты. номер один не происходит. _resources является закрытым и не может быть доступен за пределами двух вызовов методов, поэтому я не думаю, что это проблема. – poindexter12

+0

Это не похоже на проблему. Я попытаюсь сделать мою обработку более атомной, поэтому я могу попытаться уменьшить эту ошибку. Если это исправляет мою проблему, я все равно проголосую за вас :) – poindexter12

0

В дополнение к ответу Aaronaught в:

Это также выглядит вполне возможно два потока приобрести семафор, то один, чтобы войти в критическую секцию в RequestResource(), а другой блок, а затем первый поток завершения всех его работу и возвращение объекта в очередь с ReleaseResource() перед тем, как второй поток просыпается и имеет возможность деактивировать. Это создаст впечатление двух потоков, получающих один и тот же объект.

+0

в принципе, вы правы. IResource занимает около 10 секунд, чтобы выполнить какую-то работу, поэтому это не проблема. «Ресурс» повторно используется, как только его работа завершается другим потоком. я могу сказать, что «Ресурс» используется в то же время разными потоками, потому что процесс очень синхронный, а в середине обработки он начинается и уничтожает мое приложение. – poindexter12

Смежные вопросы