首页 新闻 会员 周边

双队列读写线程安全问题(重提)

0
悬赏园豆:10 [已解决问题] 解决于 2013-04-20 11:17
 1 public class DoubleCacheQueue<T>
 2     {
 3  
 4         public DoubleCacheQueue()
 5         { }
 6         public T Dequeue()
 7         {
 8             T t = default(T);
 9            
10                 if (readQueue.Count > 0)
11                     t= readQueue.Dequeue();
12                 else
13                 {
14                     writeQueue = Interlocked.Exchange<Queue<T>>(ref readQueue, writeQueue);                   
15                 }           
16             return t;
17         }
18         public void Enqueue(T item)
19         {
20                 writeQueue.Enqueue(item);
21         }
22  
23         public int Count
24         {
25             get { return readQueue.Count; }
26         }
27         //读缓冲
28         private Queue<T> readQueue = new Queue<T>();
29         //写缓冲
30         private Queue<T> writeQueue = new Queue<T>();
31  
32     }

 

补充下: 我应用的场景就是只有2个线程,我想实现一个lock free的队列 一个读线程不停的Dequeue 一个写线程不停的Enqueue 在只有2个线程一个单线程读和一个单线程写的情况下,能不能双线程安全?

garry的主页 garry | 菜鸟二级 | 园豆:495
提问于:2013-02-02 15:25
< >
分享
最佳答案
0

MSDN说的很清楚了,Queue的Item如果是公共静态的就是线程安全的。否则自己保证。

Queue本身不保证枚举的线程安全。so 你这么做不是线程安全的。

可以考虑用ConcurrentQueue<T> 类或者使用synchronized方法。

收获园豆:10
luofer | 菜鸟二级 |园豆:468 | 2013-02-22 15:13

我很奇怪,你们都不看代码的么,我代码里面用到的是俩个Queue,一个读,一个写,读写分离的。单Queue本身不是线程安全这个前提我当然知道。

garry | 园豆:495 (菜鸟二级) | 2013-02-25 10:55

@garry: 

看了啊,在极端的情况下你的读的线程可能永远读不到值。因为你写实际是先写到线程的LocalMemeray。读线程也是读自己的LocalMemeray。

具体见这个帖子:

http://www.cnblogs.com/bibiKu/archive/2013/02/19/2917161.html

见“线程通信模式”一节。

luofer | 园豆:468 (菜鸟二级) | 2013-02-27 10:40
其他回答(1)
0

使用.net4.0中的并行集合就好

ConcurrentQueue<T>

http://msdn.microsoft.com/zh-cn/library/dd267265.aspx

滴答的雨 | 园豆:3660 (老鸟四级) | 2013-02-02 16:19

这个类我知道啊,我只是想搞明白上面的那个有没有线程安全问题

支持(0) 反对(0) garry | 园豆:495 (菜鸟二级) | 2013-02-03 15:05

@garry: 

        public virtual object Dequeue()
        {
            if (this.Count == 0)
            {
                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EmptyQueue"));
            }
            object obj2 = this._array[this._head];
            this._array[this._head] = null;
            this._head = (this._head + 1) % this._array.Length;
            this._size--;
            this._version++;
            return obj2;
        }

        public virtual void Enqueue(object obj)
        {
            if (this._size == this._array.Length)
            {
                int capacity = (int) ((this._array.Length * this._growFactor) / 100L);
                if (capacity < (this._array.Length + 4))
                {
                    capacity = this._array.Length + 4;
                }
                this.SetCapacity(capacity);
            }
            this._array[this._tail] = obj;
            this._tail = (this._tail + 1) % this._array.Length;
            this._size++;
            this._version++;
        }

帮你看了下内部代码,

1、他们使用了公用资源 this._head和this._tail 。

2、这两个方法没有临界区

3、这两个变量的计算没有使用原子操作

 

所以,多线程使用这两个方法会出现并发问题。

支持(0) 反对(0) 滴答的雨 | 园豆:3660 (老鸟四级) | 2013-02-03 17:40

@滴答的雨: 

我代码里面用到的是俩个Queue,一个读,一个写,读写分离,我要确认的是在读写切换的临界区这样做是不是线程安全的

支持(0) 反对(0) garry | 园豆:495 (菜鸟二级) | 2013-02-25 10:54
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册