Java:允许人们通过门的程序

Java: Program to allow people through a Gate

提问人:mattsmith5 提问时间:11/13/2023 最后编辑:mattsmith5 更新时间:11/13/2023 访问量:41

问:

我正在编写一个程序来执行 5 个门计数,然后允许人们进入建筑物(通过执行 System.out.println)。

我有以下解决方案,使用同步。但是,有人提到此解决方案不允许排队人员的顺序锁定公平性。我怎样才能重写它以允许它?下面的信号量是否正确?

使用 Synchronized:

public class LineCount {

    int totalInLine = 0;

    public synchronized void addToLine() {
        totalInLine = totalInLine + 1;
        if (totalInLine == 5) {
             System.out.println("People may enter");
             totalInLine = 0;
        }
    }

使用信号量:

public class LineCount {

    Semaphore semaphore = new Semaphore(5, true);

    public void addToLine() throws InterruptedException {

        semaphore.acquire();
        if (semaphore.availablePermits() == 0) {
            System.out.println("People may enter");
            semaphore.release(5);
            semaphore = new Semaphore(5, true);
        }
    }
}
Java Spring-Boot 多线程 ReentrantLock

评论

0赞 mattsmith5 11/13/2023
是的,我想在第 5 次调用时打印它,然后重置并重复,道歉,我将信号量代码固定为 semaphore.availablePermits() == 0 @SolomonSlow
0赞 mattsmith5 11/13/2023
我认为第二个确保了顺序公平性,现在编写测试,谢谢@SolomonSlow
0赞 mattsmith5 11/13/2023
嗨,@SolomonSlow谢谢,你能写更新的代码吗?我可以发送积分,让我也在我的IDE中尝试一下

答:

1赞 Solomon Slow 11/13/2023 #1

版本差不多,但与版本不完全相同。但是,该版本不是线程安全的。我建议进行两项更改:SemaphoresynchronizedSemaphore

public class LineCount {

    final Semaphore semaphore = new Semaphore(5, true);   // added `final` keyword

    public void addToLine() throws InterruptedException {
        semaphore.acquire();
        if (semaphore.availablePermits() == 0) {
            System.out.println("People may enter");
            semaphore.release(5);
         // semaphore = new Semaphore(5, true);           // **Don't Do This**
        }
    }
}

原因是,如果某个线程 A 执行了该语句,则线程 B 可能会溜进来,并在线程 A 的赋值生效之前递减旧的信号量。这将允许在下次打印消息之前进行五次以上的调用。semaphore.release(5)semaphore = new Semaphore(...)

无需创建新的信号量,因为每次调用将允许另外五个调用来获取许可证。release(5)

原因主要是为了确保每个阅读代码的人都会立即理解总是引用同一个对象。finalsemaphore


更新:

然而,有人提到,该解决方案不允许排队的人实现顺序锁定公平性。synchronized

我什至猜不出这意味着什么。你应该问“某人”清楚。

您的版本每五次呼叫都会打印一条消息。它不做任何其他事情。它不会使任何呼叫者等待的时间超过其他呼叫者打印消息所需的时间。其中的“不公平”在哪里?synchronizedaddToLine

您问题的标题是“允许人们通过大门的程序”。但这里没有任何东西可以真正模拟大门。里面没有任何东西可以让任何“人”等待“门”“打开”。从字面上看,它只是一种线程安全的方法,每五次调用都会打印一条特定消息。

评论

0赞 mattsmith5 11/13/2023
嗨,我正在阅读有关同步的锁公平性的信息,baeldung.com/......“同步块不支持公平性。任何线程在释放后都可以获取锁,并且不能指定任何首选项”
0赞 Solomon Slow 11/13/2023
@mattsmith5,我知道什么是锁公平性,但我看不出它与你的程序有什么关系,除非有成千上万的线程,并且它们的调用速度比“人们可能进入”消息的速度更快可以打印。但如果是这样的话,那么你可能会遇到比“公平”更大的问题。作为一般规则,如果你认为你需要一个互斥锁(或用作互斥锁的信号量)是“公平的”,那么你的代码中可能存在设计缺陷。如果互斥锁没有受到激烈的争议,“公平”就没有优势。addToLine