希望有人能帮助我正确设计。只有在资源繁忙的情况下产生线程和工作队列
在我的TCP代码中,我有一个SendMessage()函数试图写入电线。我试图设计调用,以便在发生大量并发请求时转移到生产者/消费者模型,但同时,如果没有并发请求(为了获得最佳性能)仍保持单线程。
我在如何在没有竞争条件的情况下设计这个问题挣扎着,因为没有办法在线程之间移动锁。
我至今有点像(伪码):
SendMessage(msg) {
if(Monitor.TryEnter(wirelock,200)) {
try{
sendBytes(msg);
}
finally {
Monitor.Exit...
}
}
else {
_SomeThreadSafeQueue.add(msg)
Monitor.TryEnter(consumerlock,..
Task.Factory.New(ConsumerThreadMethod....
}
}
ConsumerThreadMethod() {
lock (wirelock) {
while(therearemessagesinthequeue)
sendBytes...
}
}
任何明显的竞争条件?
编辑:发现了最后一个缺陷。这个怎么样呢?
SendMessage(msg) {
if(Monitor.TryEnter(wirelock)) {
try{
sendBytes(msg);
}
finally {
Monitor.Exit...
}
}
else {
_SomeThreadSafeQueue.add(msg)
if (Interlocked.Increment(ref _threadcounter) == 1)
{
Task.Factory.StartNew(() => ConsumerThreadMethod());
}
else
{
Interlocked.Decrement(ref _threadcounter);
}
}
}
ConsumerThreadMethod() {
while(therearemessagesinthequeue)
lock (wirelock) {
sendBytes...
}
}
Interlocked.Decrement(ref _threadcounter);
}
所以基本上采用互锁计数器,以此来永远只产卵一个线程(如有必要)
不要忘记:KISS。只需使用线程安全队列和一个(或n,取决于最大连接数和可用内核)专用发送器线程。与导线延迟相比,无锁队列将增加很少的延迟。 – 2012-02-13 00:36:06
actuallyi在我的设计中发现了一个缺陷。两个线程可能会启动一个新线程,因为锁定必须在Factor.New调用后释放,因为我无法将锁转移到消耗线程 – 2012-02-13 00:50:14
我想我必须重写我的类以允许单个线程遍历所有线程队列(每个连接一个)呃?否则它可能是数百个被阻塞的队列(不知道线程池如何处理) – 2012-02-13 00:54:48