2012-02-13 30 views
0

希望有人能帮助我正确设计。只有在资源繁忙的情况下产生线程和工作队列

在我的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); 
} 

所以基本上采用互锁计数器,以此来永远只产卵一个线程(如有必要)

+0

不要忘记:KISS。只需使用线程安全队列和一个(或n,取决于最大连接数和可用内核)专用发送器线程。与导线延迟相比,无锁队列将增加很少的延迟。 – 2012-02-13 00:36:06

+0

actuallyi在我的设计中发现了一个缺陷。两个线程可能会启动一个新线程,因为锁定必须在Factor.New调用后释放,因为我无法将锁转移到消耗线程 – 2012-02-13 00:50:14

+0

我想我必须重写我的类以允许单个线程遍历所有线程队列(每个连接一个)呃?否则它可能是数百个被阻塞的队列(不知道线程池如何处理) – 2012-02-13 00:54:48

回答

0

无明显的种族,但TryEnter是一些严重的空闲时间的原因。我实际上认为一直使用消费者线程是最好的解决方案。如果没有什么可做的话,开销会非常小(如果设计正确的话,消费者线程在不工作时会睡着)。

现在,您为每个发送的消息创建一个新任务,导致对锁的巨大争用,因为您在使用者线程中使用了一个while循环。

编辑:由于您正在使用非阻塞套接字,单个使用者线程应该足以处理所有发送请求。单线程的吞吐量比您的网络高。如果你有更多的消费者,很难确保没有两个消费者线程在同一个套接字上发送,而没有使用互斥量序列化所有东西。我不认为在单线程和多线程之间切换是一个好主意。

由于所有工作都使用相同的互斥锁进行保护,因此您当前的“多线程”解决方案不会带来任何性能提升。它会比单个线程慢或慢。

+0

您是否为每个连接建议一个消费者线程?或者是一个通过连接队列的主线程(在客户端,它没有区别,但服务器可能有1000个连接) – 2012-02-13 00:53:28

+0

每个连接都没有一个线程可以接收数据吗?或者你在使用非阻塞套接字? – rasmus 2012-02-13 00:55:50

+0

无阻塞rasmus ... – 2012-02-13 08:24:12

相关问题