Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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_Multithreading_Deadlock_Wait - Fatal编程技术网

Java 等待/通知死锁

Java 等待/通知死锁,java,multithreading,deadlock,wait,Java,Multithreading,Deadlock,Wait,我在“Add”和“Get”方法中有一个带有阻塞机制的队列,其中第一个线程添加数据,第二个线程获取数据 public synchronized MyObj getData() { synchronized (myLock) { synchronized (this) { if (isEmpty()) { wait(0);

我在“Add”和“Get”方法中有一个带有阻塞机制的队列,其中第一个线程添加数据,第二个线程获取数据

public synchronized MyObj getData() {               
    synchronized (myLock) {
        synchronized (this) {
            if (isEmpty()) {                
                wait(0);                    
            }
        }       


        return getData();           
    }
}

public synchronized void addData(MyObj data) {
    if (!isFull()) {
        putData(data);
        synchronized (this) {
            notify();
        }
    }
}
在上面的代码中,如果第一个线程试图获取数据,而队列为空,我将通过wait(0)进行等待,直到另一个线程通过notify()将数据添加到队列中,以释放等待

现在,我想在队列已满且有人试图向其添加更多数据时添加另一个“锁”:

public synchronized MyObj getData() {               
    synchronized (myLock) {
        synchronized (this) {
            if (isEmpty()) {                
                wait(0);                    
            }
        }       

        synchronized (this) {
            notify();
        }
        return getData();           
    }
}

public synchronized void addData(MyObj data) {
    synchronized (myLock) {
        synchronized (this) {
            if (isFull()) {
                wait(0);
            }
        }
    }

    synchronized (this) {
        notify();
        }
        PutData(data);
}
结果并不是我所期望的,我想我得到了一个死锁,因为进程被卡住了

更新

这是我获取数据的方式:

queueSize--;
startPointer = (startPointer + 1) % mqueueSize;
data = (String) queue[startPointer];
这就是我添加数据的方式

  queueSize++;
  endPointer = (endPointer + 1) % mqueueSize;
  queue[endPointer] = data;

public synchronized boolean isEmpty() {
        return queueSize== 0;
    }

    public synchronized boolean isFull() {
        return queueSize== mqueueSize;
    }

你为什么不进去看看。也许它在你的情况下会有用


请特别注意,如果在构造函数中指定队列的容量,那么队列将阻塞。

为什么不查看。也许它在你的情况下会有用


请特别注意,如果您在构造函数中指定队列的容量,那么队列将阻塞。

从方法签名中删除
synchronized
关键字,这意味着您持有整个方法调用的
this
监视器--
synchronized(this)
块只是多余的

编辑:


…然后在
myLock
上调用wait和notify,而不是
this
。并且完全忘记在
上同步此
。这是因为在等待时(在当前代码中的
This
),您没有释放
myLock
锁,因此另一个线程无法访问
notify()

从方法签名中删除
synchronized
关键字,这意味着您为整个方法调用持有
this
监视器--
synchronized(this)
块只是冗余的

编辑:


…然后在
myLock
上调用wait和notify,而不是
this
。并且完全忘记在
上同步此
。这是因为在等待时(在当前代码中的
This
),您没有释放
myLock
锁,因此另一个线程无法访问
notify()

if
替换为
while
。如果集合真的不是空的/不是满的,那么仔细检查也无妨

你真的不需要两把锁。单锁也可以很好地工作,应该简单得多

public synchronized T get()
{
    while(isEmpty())
        wait(0);

    notifyAll();

    return super.get();

}

public synchronized put(T t)
{

    while(isFull())
        wait(0);

    super.put(t);

    notifyAll();

}

当某些内容发生更改时,所有线程都将唤醒。但是如果他们不能完成他们的工作,他们将等待下一个
通知
期间将
如果
替换为
。如果集合真的不是空的/不是满的,那么仔细检查也无妨

你真的不需要两把锁。单锁也可以很好地工作,应该简单得多

public synchronized T get()
{
    while(isEmpty())
        wait(0);

    notifyAll();

    return super.get();

}

public synchronized put(T t)
{

    while(isFull())
        wait(0);

    super.put(t);

    notifyAll();

}

当某些内容发生更改时,所有线程都将唤醒。但是如果他们不能完成他们的工作,他们将等待下一个
通知
为什么有三个
同步的
语句?
wait(0)
仅释放
this
上的锁,因此只需保留该锁,并从方法和
synchronized(myLock)
中转储
synchronized

无论何时调用某个对象上的wait(在本例中,您调用的是
this
),该对象上的锁都会自动释放,以允许另一个线程继续。但是您从来没有在
myLock
上调用wait(您也不应该这样做,因为您已经在
this
上调用了)。该部分是多余的,会导致死锁

考虑这个场景:应该添加的线程在
myLock
上获得锁,但发现队列已满,所以等待。此等待不会解除
myLock
上的锁定。另一个线程想要获取数据,但无法进入
synchronized
块,因为第一个线程没有释放
myLock
上的锁


结论:删除
synchronized(myLock)
块。

为什么有三个
synchronized
语句?
wait(0)
仅释放
this
上的锁,因此只需保留该锁,并从方法和
synchronized(myLock)
中转储
synchronized

无论何时调用某个对象上的wait(在本例中,您调用的是
this
),该对象上的锁都会自动释放,以允许另一个线程继续。但是您从来没有在
myLock
上调用wait(您也不应该这样做,因为您已经在
this
上调用了)。该部分是多余的,会导致死锁

考虑这个场景:应该添加的线程在
myLock
上获得锁,但发现队列已满,所以等待。此等待不会解除
myLock
上的锁定。另一个线程想要获取数据,但无法进入
synchronized
块,因为第一个线程没有释放
myLock
上的锁


结论:删除
synchronized(myLock)
块。

如前所述,您的代码有太多
synchronized
注释。此外,在
if
条件中检查
等待
开启的条件,但理想情况下应在
while
循环中检查该条件以避免。下面是修复这些问题的代码概要

// _isEmpty and _getData are private unsynchronized methods
public MyData get() throws InterruptedException {
  // wait and notify should be called from a block
  // synchronized on the same lock object (here myLock)       
  synchronized (myLock) {
    // the condition should be tested in a while loop
    // to avoid issues with spurious wakeups
    while (_isEmpty()) {
      // releases the lock and wait for a notify to be called
      myLock.wait();
    }
    // when control reaches here, we know for sure that
    // the queue is not empty
    MyData data = _getData();
    // try to wake up all waiting threads - maybe some thread
    // is waiting for the queue not to be full
    myLock.notifyAll();
  }
}

// _isFull and _putData are private unsynchronized methods
public void put(MyData obj) throws InterruptedException {
  synchronized (myLock) {
    while (_isFull()) {
      myLock.wait();
    }
    _putData(obj);
    myLock.notifyAll();
  }
}

如前所述,您的代码有太多的
同步的
注释。此外,在
if
条件中检查
等待
开启的条件,但理想情况下应在
while
循环中检查该条件以避免。下面是修复这些问题的代码概要

// _isEmpty and _getData are private unsynchronized methods
public MyData get() throws InterruptedException {
  // wait and notify should be called from a block
  // synchronized on the same lock object (here myLock)       
  synchronized (myLock) {
    // the condition should be tested in a while loop
    // to avoid issues with spurious wakeups
    while (_isEmpty()) {
      // releases the lock and wait for a notify to be called
      myLock.wait();
    }
    // when control reaches here, we know for sure that
    // the queue is not empty
    MyData data = _getData();
    // try to wake up all waiting threads - maybe some thread
    // is waiting for the queue not to be full
    myLock.notifyAll();
  }
}

// _isFull and _putData are private unsynchronized methods
public void put(MyData obj) throws InterruptedException {
  synchronized (myLock) {
    while (_isFull()) {
      myLock.wait();
    }
    _putData(obj);
    myLock.notifyAll();
  }
}

为什么单锁就足够了?如果线程试图在一个循环中将数据添加到一个完整的队列中,它会不断地点击“if(!isFull())。@kenny这可能不是必需的,但一般情况下可能有多个线程在等待。为什么单锁就足够了?如果线程将尝试