2

我有一段代码,它应该由低于N的线程的最大数量执行,并且线程调用someFunction()的顺序应该反映在它们进入该部分的顺序,即FIFO顺序。最多N个线程以FIFO的顺序执行的代码段

如果我使用Semaphore,我无法控制线程进入该部分的顺序。

“没有保证顺序,例如FIFO或LIFO,其中阻塞的 线程进入信号量。”

的初步尝试:

class someClass 
{ 
    static volatile Semaphore semaphore; 
    ... 

    someClass() 
    { 
     semaphore = new Semaphore(N,N) 
    } 

    someType someFunction(InputType input) 
    { 
     try 
     { 
      semaphore.WaitOne(); 
      /* Section Begins */ 
      var response = someHeavyJob(input); // submitted to the server 
      return response; 
      /* Section Ends */ 
     } 
     finally 
     { 
      semaphore.Release(); 
     } 
    } 
} 

如果我结合了信号量和ConcurrentQueue如下线程可能会回来与由其他线程所带来的请求,你会需要的其他部分显著变化的响应码。 什么是采用以下问题的.NET 4.5溶液:

  1. 允许低于N中的代码
  2. 顺序在哪些线程进入区段的区段的最大线程数是FIFO
  3. 线程将获得他们所带来的请求的响应(而不是根据其他线程带来的请求)

    class someClass 
    { 
        static volatile ConcurrentQueue<someType> cqueue; 
        static volatile Semaphore semaphore; 
        ... 
    
        someClass() 
        { 
         cqueue = new ConcurrentQueue<someType>(); 
         semaphore = new Semaphore(N,N) 
        } 
    
        someType someFunction(Request request) 
        { 
         try 
         { 
          cqueue.enqueue(request); 
          semaphore.WaitOne(); 
          Request newrequest; 
          cqueue.TryDequeue(out newrequest); 
    
          /* Section Begins */ 
    
          var response = someHeavyJob(Request newrequest); // submitted to the server 
          return response; 
          /* Section Ends */ 
         } 
         finally 
         { 
          semaphore.Release(); 
         } 
        } 
    } 
    

更新: 我在澄清我的问题: SomeHeavyJobs()函数是对正在处理此工作的服务器的阻止调用。

UPDATE2: 谢谢大家的回答。备案:我结束了使用FIFO Semaphore

+0

你能更具体吗?有点难以理解你的一些类和某种类型...你想在代码中修复什么 – Madman

+0

我想要做的是将执行一段代码的线程数限制为N,其中N> 1并且仍然保持先进先出顺序 – matcheek

+0

如果您正在讨论几个同时执行的线程,那么谈论“订单”有点难。你能详细说明一下吗?另外,你的队列和信号量应该是'readonly',而不是'volatile'。 – Groo

回答

1

“如果我结合了信号量和ConcurrentQueue如下线程可能会回来与由其他线程所带来的请求,你会需要的代码的其他部分显著变化的响应。”

我讨厌这样说,但我会建议“中的代码其他部分的变化”,虽然我不知道多少“意义”,这将有。

Typicaly,这样的要求得到满足如你所说,通过排队包含对原始类实例的引用,以便响应可以“返回”来请求这些对象的消息。如果发起者都是来自某个'messagehandler'类的后代,那么这会使调用该函数的线程(它应该是messagehandler的成员)更容易。一旦线程执行了该函数,他们就可以调用消息处理程序的'onCompletion'方法。 'onCompletion'既可以表示发起者正在等待的事件(同步),也可以将某事列入发起者的私有P-C队列(异步)。

所以,一个BlockingCollection,一个消费者线程,并明智地使用C++/C#继承/多态性应该做的工作。

奇怪的是,这几乎就是我正在用我当前的嵌入式ARM项目强制实现的。用于config/debug/log的命令行界面线程现在非常庞大,即使在“Thumb,Optimize of size”模式下也需要大量600字的堆栈。不能再允许直接调用SD文件系统,现在必须将自己排队到运行SD卡的线程(系统中运行FAT32的堆栈最大),然后等待SD线程的信号量调用它的方法并在完成时发出信号。

这是确保按顺序进行呼叫并保持工作的经典方式。它基本上只有一个线程的线程池。

就像其他海报写的一样,任何其他的方法很可能是,错的......'勇敢的'。

1

你看过Smart Thread Pool

[编辑]

如果我仍然得到这个问题的权利,正如我在评论中所指出的,我不相信,一个多线程的解决方案是这一问题的可行。

如果ķ不能前任务K-1启动任务已经完成,那么你只需要一个单独的线程来执行它们。如果允许您并行执行某些组合任务,那么您需要准确指定规则。

+0

我相信这种挑战非常普遍,可能存在本地.NET解决方案。 – matcheek

+0

@matcheek:我发现挑战*罕见*,实际上。你不能确保一个线程在它碰到锁之前不会被重新安排。这意味着您需要特别检查您的前一个任务是否已经开始执行(这可能与设置volatile int计数器一样简单),然后继续执行下一个任务。但即使如此,线程也可以轻松地取消预定,并将执行顺序混淆起来。 – Groo

+0

它看起来像我切割所有不必要的细节方法,使问题更清晰,让我回来。我在剧集中没有提到的是一些重要的作业实际上是I/O,是什么导致线程等待来自处理作业的服务器的响应。 – matcheek

1

也哪些线程调用someFunction(顺序)应 反映在它们在进入部的顺序,也就是 FIFO顺序

这是不可能通过原则。

semaphore.WaitOne(); //#1 
var response = someHeavyJob(input); //#2 

即使是信号灯被严格FIFO,以下可能发生:

  1. 的所有线程以FIFO的顺序(1)
  2. 所有线程都从CPU取消调度进入部分(1和2之间2)
  3. 所有线程都改期按随机顺序,甚至LIFO顺序(1和2)
  4. 所有线程开始以任意顺序(2)
  5. 进入someHeavyJob之间

你永远无法保证在一个特定的顺序,该线程将“进入”功能。

至于FIFO信号,您可以用锁和队列构建一个信号量自己。看起来你已经做到了,并发布了代码。据我所知,这种方法是正确的。

+0

我认为他期望建立一个系统,在这个系统中,如果线程被取消预定,然后按随机顺序重新排定,他们仍然会等待轮到他进入方法,即队列中位置k的线程被重新安排,但会被放回睡眠状态直到线程k-1 ... 1进展。 – Tudor

+0

@Tudor,我也觉得他想要。但是这是不可能的。该线程甚至可以在该方法内切换命令*。他可以控制有关访问该部分的顺序。 – usr

+0

对于关键部分,解决方案的一个好的近似可以是面包店算法http://en.wikipedia.org/wiki/Lamport's_bakery_algorithm。 我还没有发现任何类似的代码段允许多达N个线程。 – matcheek