does Monitor.Wait Needs synchronization?

前端 未结 3 917
予麋鹿
予麋鹿 2020-12-11 17:05

I have developed a generic producer-consumer queue which pulses by Monitor in the following way:

the enqueue :

    public void EnqueueTask(T task)
           


        
3条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-11 17:49

    From the MSDN description of Monitor.Wait():

    Releases the lock on an object and blocks the current thread until it reacquires the lock.

    The 'releases the lock' part is the problem, the object isn't locked. You are treating the _locker object as though it is a WaitHandle. Doing your own locking design that's provably correct is a form of black magic that's best left to our medicine man, Jeffrey Richter and Joe Duffy. But I'll give this one a shot:

    public class BlockingQueue {
        private Queue queue = new Queue();
    
        public void Enqueue(T obj) {
            lock (queue) {
                queue.Enqueue(obj);
                Monitor.Pulse(queue);
            }
        }
    
        public T Dequeue() {
            T obj;
            lock (queue) {
                while (queue.Count == 0) {
                    Monitor.Wait(queue);
                }
                obj = queue.Dequeue();
            }
            return obj;
        }
    }
    

    In most any practical producer/consumer scenario you will want to throttle the producer so it cannot fill the queue unbounded. Check Duffy's BoundedBuffer design for an example. If you can afford to move to .NET 4.0 then you definitely want to take advantage of its ConcurrentQueue class, it has lots more black magic with low-overhead locking and spin-waiting.

提交回复
热议问题