了解ReusableBarrier问题(来自'信号量小书')

时间:2011-05-08 02:12:56

标签: java concurrency

问题陈述如下:

通常,一组协作线程将在循环中执行一系列步骤 在每个步骤之后在屏障处同步。对于这个应用程序,我们需要一个可重用的 在所有线程都通过后锁定自身的屏障。

鉴于解决方案是:

1 # rendezvous
2
3 mutex.wait()
4     count += 1
5     if count == n:
6         turnstile2.wait() # lock the second
7         turnstile.signal() # unlock the first
8 mutex.signal()
9
10 turnstile.wait() # first turnstile
11 turnstile.signal()
12
13 # critical point
14
15 mutex.wait()
16     count -= 1
17     if count == 0:
18         turnstile.wait() # lock the first
19         turnstile2.signal() # unlock the second
20 mutex.signal()
21
22 turnstile2.wait() # second turnstile
23 turnstile2.signal()

假设我们将这个屏障用于2个线程,我们通过此屏障泵送100个线程。当第二个线程已解锁旋转门(7)并到达线9时,现在,线程3出现并且,
它递增计数,
计数> n所以它释放互斥,
由于十字转门被解锁,它也达到临界点,
类似地,线程4,线程5,线程6可以执行临界点,执行它超过2次 什么阻止他们穿过线程2前面的障碍?或者我的理解在这里错了吗?

2 个答案:

答案 0 :(得分:1)

问题陈述表明(第22页):

  

您可以假设有n个线程,并且该值存储在a中   变量n,可从所有线程访问。

因此,如果n = 2并且有100个线程,则您违反了此假设,解决方案将无效。

答案 1 :(得分:0)

也许这超出了这个问题,但是这里说:只要最多n个线程在屏障代码内,所列出的解决方案就是我所能说的正确。保证这一点的一种方法是总共只有n个线程。

本书还提供了一种不同的方法来确保只有n个线程位于给定区域内:Multiplex(使用信号量来保证最多n个线程一次使用给定的资源)。像这样使用它:

general_barrier.init(n):
    occupancy = Semaphore(n)
    barrier = Barrier(n)
general_barrier.enter():
    occupancy.wait()
    barrier.enter()
    barrier.leave()
general_barrier.leave():
    occupancy.signal()

您可以这样使用它:

shared state:
    gbarrier = general_barrier(n)
each of m threads (where m > n, but in particular try m > 2*n):
    while True:
        gbarrier.enter()
        something critical
        gbarrier.leave()

在问题的代码中,您可以在第2行放置occupancy.wait(),在第24行放置occupancy.signal(),基本上可以使用此解决方案。请注意,问题中的代码在临界点后面等同于barrier.leave(),即general_barrier.leave(),而不是之前的{{1}}。我并不认为这对于正确性很重要,尽管它对于执行的上下文切换次数可能很重要。也许,在某些情况下。建议读者自行决定; - )