Java 监视器代替二进制信号量

标签 java multithreading concurrency locking monitoring

我正在做一项学校作业,我应该使用监视器同步两个线程。在这种情况下,每个监视器控制一段铁路的访问,并且火车需要锁定该段铁路,以便其他监视器无法访问它或必须等待直到该段轨道空闲。我以前从未使用过显示器,所以我确信问题在于我对显示器工作原理的了解有限。火车及其线程本身工作得很好,我已经在相同的代码中成功地使用了二进制信号量。现在我正在尝试用监视器替换信号量。

我基本上想知道条件和锁到底是如何工作的。我读过不同的博客和论坛,但似乎无法理解这个概念。

重要说明:我不允许使用 synchronized 关键字。

当我运行当前代码时,出现以下错误。错误发生在 leave 方法中的 ocpied.signal() 处:

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signalAll(AbstractQueuedSynchronizer.java:1956)

这是到目前为止的代码:

public class Monitor {

private final Lock lock = new ReentrantLock();
private final Condition occupied = lock.newCondition();

private boolean isOccupied = false;

private int id;

public Monitor(int id) {
    super();
    this.id = id;
}

public void enter(){
    lock.lock();
    try {
        if(isOccupied)
            occupied.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    isOccupied = true;
}

public boolean tryEnter(){
    if(isOccupied){
        return false;
    }else{
        enter();
        return true;
    }
}

public void leave(){
    lock.unlock();
    isOccupied = false;
    occupied.signal();
}

}

如果有任何帮助和/或关于问题的想法,我将不胜感激。

谢谢!

最佳答案

你的锁定太粗略了。作为一般模式,除非有非常特殊的情况,否则所有锁定都应采用以下形式:

lock.lock();
try {
    ....
} finally {
     lock.unlock();
}

您没有使用此模式(甚至以不同的方法锁定和解锁)。

从技术上讲,您的问题是当您没有持有lock监视器时,您正在发出占用状态信号。

在您的程序中,轨道部分上的“独占”锁不应是实际的 Java 锁机制,而是 boolean 变量 isOccupied。更改您的代码,以便这两个方法执行正确的 try...finally block ,而且,您应该将您的 Condition 重命名为“未占用”,并反转保留它的逻辑。

public void enter(){
    lock.lock();
    try {
        while(isOccupied)
            unoccupied.await();
        isOccupied = true;
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
}


public void leave(){
    lock.lock();
    try {
        isOccupied = false;
        unoccupied.signal();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
}

关于Java 监视器代替二进制信号量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18873686/

相关文章:

java - 两个Maven Dependency 最新版本和旧版本冲突

python - 在Python多处理模块中使用Pool和Queue

c++ - 在现代c++中,当 protected 资源需要通过getter作为shared_ptr返回时,如何设计单写和多读?

java - 我们应该在 Java 中处理未经检查的异常吗?

java - 什么时候使用Statement比PreparedStatement更好?

Java Runnable 具有大量任务 Rainbow Table

java - 连接被拒绝 - Java 客户端/服务器

java - 如何在play框架作业中下载图像?

java - JPA/Hibernate + 从 onetomayrelation 获取特定项目

multithreading - 主线程阻塞并行线程?