1

假设我有一堆工作线程,我想避免线程花费时间来确定谁得到什么工作。

假设每个线程都有一个与之关联的数字/ID。有一份工作清单。队列中的每个作业都有一个与之关联的 ThreadID。

ThreadID
1          = Job Available
0          = Job Finished
> 1        = Active ==> ThreadID = ID of thread working on the job

对于要处理作业的线程,它会扫描列表并找到第一个 ThreadID = 1 并尝试接受该作业。

这种方式线程消耗作业。(显然他们会睡觉,需要被正确唤醒,但现在忽略所有这些)

问题是,两个线程可能同时尝试处理同一个工作,这很糟糕。

为了解决这个问题,每个线程只需将它的线程 ID 分配给线程 ID,这将阻止其他线程工作,除非在写入线程 ID 之前读取一个线程。

ThreadID      Thread 11         Thread 12            ....
1             ThreadID == 1?                         Job available
                                ThreadID == 1?       Job available
11            ThreadID = 11                          Try to take job
12                              ThreadID == 12       Try to take job
              ThreadID == 11?                        Job was taken by another thread
                                ThreadID == 12?      (If no other competing threads then thread 12 got the job)

不确定该表是否有意义,但它显示了两个线程竞争该工作。他们都认为他们有这份工作,但无论哪个线程实际上在 ThreadId 中有他们的编号,都得到了这份工作(这将是最后一个写入 ThreadID 的线程)。

我相信这样的方案不需要锁并且安全吗?它是否正确?

4

2 回答 2

1

通常,当您有一组作业和多个线程来处理作业时,您将通过锁定或更复杂的非阻塞机制(例如ConcurrentQueue<T>在 .NET 4 中)将作业放入线程安全队列中。

每个线程从队列中获取一个作业并处理它。如果线程无法完全处理它,您需要一些机制来返回队列。

但是,如果您想继续使用将作业标记为由线程处理的方法,这样做很简单,但您需要使用锁定来确保一次只有一个线程修改作业。

于 2013-07-02T03:18:53.570 回答
0

我认为您所描述的“比较-写入-比较”方法是不够的。看这个案例:

  Thread 0          Thread 1

reads <empty>
                  reads <empty> 
writes 0
reads 0
runs task
                  writes 1
                  reads 1
                  runs task

这种交错将使两个线程执行相同的任务。我可能在您的描述中遗漏了某些内容,但是如果我正确理解了您的算法,那么这应该与其合理性相矛盾。

于 2013-07-02T06:00:07.867 回答