我想做一个 LockFree Queue,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;namespace MutiThreadSynchronizationTest2
{
class Program
{
//test2 used
static void Main(string[] args)
{
Producer producer = new Producer();
Customer customer = new Customer();
Thread produceThread = new Thread(new ThreadStart(producer.Produce));
Thread consumeThread = new Thread(new ThreadStart(customer.Consume)); Console.WriteLine("start\n"); DateTime startTime = DateTime.Now; produceThread.Start(); Thread.Sleep(50);
consumeThread.Start();
produceThread.Join();
consumeThread.Join(); produceThread.Abort();
consumeThread.Abort(); DateTime endTime = DateTime.Now;
TimeSpan ts = endTime - startTime; Console.WriteLine("Used" + ts.TotalMilliseconds); Console.ReadLine();
} } public static class ProductQueue
{
public static Queue<Product> productQueue = new Queue<Product>();
}
public class Product
{
public Product(string content)
{
Content = content;
} private string _content;
public string Content
{
get
{
return _content;
} set
{
_content = value;
}
}
public override string ToString()
{
return Content;
} }
public class Producer
{
public void Produce()
{
for (int count = 0; count < 5000; count++)
{
// doing something;
Thread.Sleep(5); Random ra = new Random();
int c = ra.Next(2, 6);
//enqueue 1-5 products
for (int i = 1; i < c; i++)
{
if (ProductQueue.productQueue.Count > 2)
{
ProductQueue.productQueue.Enqueue(new Product(i.ToString()));
}
else
{
lock (ProductQueue.productQueue)
{ ProductQueue.productQueue.Enqueue(new Product(i.ToString()));
}
}
} }
}
}
public class Customer
{
public void Consume()
{
while (true)
{
//system is doint something else
Thread.Sleep(2);
if (ProductQueue.productQueue.Count > 0)
{
if (ProductQueue.productQueue.Count > 2)
{
ProductQueue.productQueue.Dequeue();
}
else
{
lock (ProductQueue.productQueue)
{
ProductQueue.productQueue.Dequeue();
}
}
}
else
{
break;
}
}
}
}}
这段代码 经常会出现ArgumentException异常
“源数组长度不足。请检查 srcIndex 和长度以及数组的下限。”
我的想法是,如果Queue里面的Item大于1个,按理来说EnQueue和DeQueue就可以同时进行不需要Lock了啊。
为什么会出错呢?期待原理性的回答,说一定要用Lock不给分。我就是纯粹蛋痛钻牛角尖一下而已
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;namespace MutiThreadSynchronizationTest2
{
class Program
{
//test2 used
static void Main(string[] args)
{
Producer producer = new Producer();
Customer customer = new Customer();
Thread produceThread = new Thread(new ThreadStart(producer.Produce));
Thread consumeThread = new Thread(new ThreadStart(customer.Consume)); Console.WriteLine("start\n"); DateTime startTime = DateTime.Now; produceThread.Start(); Thread.Sleep(50);
consumeThread.Start();
produceThread.Join();
consumeThread.Join(); produceThread.Abort();
consumeThread.Abort(); DateTime endTime = DateTime.Now;
TimeSpan ts = endTime - startTime; Console.WriteLine("Used" + ts.TotalMilliseconds); Console.ReadLine();
} } public static class ProductQueue
{
public static Queue<Product> productQueue = new Queue<Product>();
}
public class Product
{
public Product(string content)
{
Content = content;
} private string _content;
public string Content
{
get
{
return _content;
} set
{
_content = value;
}
}
public override string ToString()
{
return Content;
} }
public class Producer
{
public void Produce()
{
for (int count = 0; count < 5000; count++)
{
// doing something;
Thread.Sleep(5); Random ra = new Random();
int c = ra.Next(2, 6);
//enqueue 1-5 products
for (int i = 1; i < c; i++)
{
if (ProductQueue.productQueue.Count > 2)
{
ProductQueue.productQueue.Enqueue(new Product(i.ToString()));
}
else
{
lock (ProductQueue.productQueue)
{ ProductQueue.productQueue.Enqueue(new Product(i.ToString()));
}
}
} }
}
}
public class Customer
{
public void Consume()
{
while (true)
{
//system is doint something else
Thread.Sleep(2);
if (ProductQueue.productQueue.Count > 0)
{
if (ProductQueue.productQueue.Count > 2)
{
ProductQueue.productQueue.Dequeue();
}
else
{
lock (ProductQueue.productQueue)
{
ProductQueue.productQueue.Dequeue();
}
}
}
else
{
break;
}
}
}
}}
这段代码 经常会出现ArgumentException异常
“源数组长度不足。请检查 srcIndex 和长度以及数组的下限。”
我的想法是,如果Queue里面的Item大于1个,按理来说EnQueue和DeQueue就可以同时进行不需要Lock了啊。
为什么会出错呢?期待原理性的回答,说一定要用Lock不给分。我就是纯粹蛋痛钻牛角尖一下而已
解决方案 »
- |ZYCWPF| 为什么Style.DataTragger中的Setter无法设置Text属性,是不是这个只能设置样式,而数据字段不可以设置呢?
- 有调用过sql dts包的吗?请教下
- sharpmap 画矩形问题
- c#动态创建属性
- 关于c#中按钮
- 支付计费问题
- datagirdview绑定一个集合
- 兄弟们,如何判断有多少台电脑与本地电脑或其他某一台电脑的连接数,谢谢了,也送分给你们了.
- 关于字符串处理:有人知道C#中取一个字符串的前几个字母做判断用什么函数吗?在线等,谢谢
- 如何部署和分发.NET应用程序?
- C# 调用WIN32的SendMessage方法里面的参数都是干什么的?
- 一首很简单的计算题
lock free queue
http://www.google.com.hk/search?hl=zh-CN&source=hp&biw=1436&bih=709&q=lock+free+queue&btnG=Google+%E6%90%9C%E7%B4%A2&aq=f&aqi=&aql=&oq=
Produer不是只管往queue里填数据吗?那要Lock它干吗?
Customer就是要取出数据。你在while里有判断
if (ProductQueue.productQueue.Count > 0)
{
//dequeue
}
else
{
break;
}
也不需要lock
你这里只有一个消费者。
对的,我也是这个想法,现在问题可能就归结在Queue内部实现不支持多线程吧?我用LinkedList实现个去queue试下
为什么会出错呢?期待原理性的回答,说一定要用Lock不给分。我就是纯粹蛋痛钻牛角尖一下而已”,其实这就无法让人很好地回答你的问题,以为你自己把别人的真正回答给否定了。
if (ProductQueue.productQueue.Count > 0)
{
if (ProductQueue.productQueue.Count > 2)
{[code=C#][/code]这样的程序吧!呵呵,如果你知道一旦“if (ProductQueue.productQueue.Count > 0)”这条语句执行完,下一条语句执行之前此时.Count就可能为0,你就不会写出太烂的、过分拼凑式的无意义代码了。
MSDN讲的很清楚,queue的静态方法是线程安全的,实例方法是非线程安全的,看不懂说了那么多,再说什么,能不能先把原理搞明白再说,给你看看Queue的Enqueue 和Dequeue的实现源码,如果能看出来哪里是线程安全的话,那就没必要再沟通了public void Enqueue(T item)
{
if (this._size == this._array.Length)
{
int capacity = (int) ((this._array.Length * 200L) / 100L);
if (capacity < (this._array.Length + 4))
{
capacity = this._array.Length + 4;
}
this.SetCapacity(capacity);
}
this._array[this._tail] = item;
this._tail = (this._tail + 1) % this._array.Length;
this._size++;
this._version++;
}public T Dequeue()
{
if (this._size == 0)
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyQueue);
}
T local = this._array[this._head];
this._array[this._head] = default(T);
this._head = (this._head + 1) % this._array.Length;
this._size--;
this._version++;
return local;
}
class Program
{
static void Main(string[] args)
{ _IntQueue = new Queue<int>();
_IntQueue.Enqueue(1);
Thread t1 = new Thread(new ThreadStart(Enqueue));
t1.Start();
Thread t2 = new Thread(new ThreadStart(Dequeue));
t2.Start();
Console.ReadLine(); }
static void Enqueue()
{
while (true)
{
_IntQueue.Enqueue(DateTime.Now.Millisecond);
}
} static void Dequeue()
{
while (true)
{
_IntQueue.Dequeue();
}
}
static Queue<int> _IntQueue;
}