Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 理解可重用障碍问题(来自信号量小书)_Java_Concurrency - Fatal编程技术网

Java 理解可重用障碍问题(来自信号量小书)

Java 理解可重用障碍问题(来自信号量小书),java,concurrency,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 firs

问题陈述如下:

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

给出的解决方案是:

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出现并且,
它增加计数,
count>n,因此它会释放互斥锁,
由于旋转栅门已解锁,因此也达到临界点,
同样,线程4、线程5、线程6可以执行临界点,执行超过2次。

是什么阻止他们通过线程2前面的屏障?还是我的理解有误?

问题陈述指出(第22页):

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


因此,如果n=2且有100个线程,则违反了此假设,解决方案将不起作用。

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

这本书还提供了一种确保给定区域内只有n个线程的不同方法:多路复用(使用信号量保证一次最多有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()
您可以这样使用它:

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()

在问题的代码中,您可以将
occulation.wait()
放在第2行,将
occulation.signal()
放在第24行,基本上就是这个解决方案。请注意,问题中的代码将相当于
barrier.leave()
的内容放在临界点之后,即在
general\u barrier.leave()
中,而不是像我所做的那样放在临界点之前。我认为这与正确性无关,尽管它可能与执行的上下文切换的数量有关。也许,在某些情况下。建议读者自行决定;-)

在本例中,我们设置了一个期望2个线程的屏障,即当第二个线程到达时,它应该让两个线程通过,并且它应该阻止第三个线程,直到第四个线程到达。因此,如果我们通过它泵送100个线程,它应该允许成对的线程通过它。然而,在上面的示例中,我认为如果第二个线程在第9行休眠,它将中断并让所有线程通过。此外,在讨论并发兴趣邮件列表之后,在书中的示例中,似乎期望屏障在一个循环中由相同的N个线程集使用。它不是一个可以被多组N线程使用的通用屏障…对。听起来你所想的是一个屏障,它只允许线程分三批进入关键部分,并要求三个线程在进入下三个之前退出。那样的话,我想你会喜欢第五章的。这样的问题有好几个。