同步块。僵局。 Java
Syncronized blocks. DeadLock. Java
请帮帮我。此代码可能在哪里被阻止?
我认为它不应该阻止。 getItem 等待的线程,
详细信息出现在存储中,并在从存储中获取任何项目时通知任何人。 putItem 通知的线程,何时
它会将任何详细信息放入存储中,并等待它是否已满。这样对吗?
我认为不,因为出现僵局
对不起我的英语。这不是我的母语。
public class Storage<E> {
ArrayList<E> details;
private Integer limit; //Storage Capacity
final MonitorObject expectItemObject; //objects for synchronization
final MonitorObject expectPlaceObject;
public Storage(Integer limit)
{
this.limit = limit;
expectItemObject = new MonitorObject();
expectPlaceObject = new MonitorObject();
details = new ArrayList<>(limit);
}
public Integer getSize()
{
int detNo=0;
synchronized (expectPlaceObject)
{
synchronized (expectItemObject) {
detNo = details.size();
}
}
return detNo;
}
public void putItem(E e) throws InterruptedException
{
synchronized (expectPlaceObject)
{
while (getSize().equals(limit)) { //ensure that we have a place
expectPlaceObject.wait(); //sleep if storage is full
}
synchronized (expectItemObject) { //there is no trouble in inners synchronized, as the second is not blocking.
details.add(e);
expectItemObject.notify(); //if anybody,who expect item, sleep, awake him.
}
}
}
public E getItem() throws InterruptedException
{
E detail;
synchronized (expectItemObject)
{
while (getSize() == 0) {
expectItemObject.wait(); //sleep if storage is empty
}
synchronized (expectPlaceObject) {
detail= details.remove(0);
expectPlaceObject.notify(); //if anybody,who expect place sleep, awake him.
}
}
return detail;
}
}
在 putItem
和 getItem
中,您正在同步两个不同的对象,expectPlaceObject
和 expectItemObject
。
问题是您在这两种方法中以不同的顺序同步它们。可能发生的情况如下:
- 线程 A 调用
putItem
并锁定 expectedItemObject
- 同时线程 B 调用
getItem
并锁定 expectedPlaceObject
- 接下来两个线程都想锁定另一个线程已经锁定的对象,这会导致死锁。
调查死锁的一个好方法是使用 jstack 获取进程的线程转储。输出将列出您的死锁。
尝试用这个改变你的 getSize() 方法:
public Integer getSize() {
return details.size();
}
请帮帮我。此代码可能在哪里被阻止? 我认为它不应该阻止。 getItem 等待的线程, 详细信息出现在存储中,并在从存储中获取任何项目时通知任何人。 putItem 通知的线程,何时 它会将任何详细信息放入存储中,并等待它是否已满。这样对吗? 我认为不,因为出现僵局 对不起我的英语。这不是我的母语。
public class Storage<E> {
ArrayList<E> details;
private Integer limit; //Storage Capacity
final MonitorObject expectItemObject; //objects for synchronization
final MonitorObject expectPlaceObject;
public Storage(Integer limit)
{
this.limit = limit;
expectItemObject = new MonitorObject();
expectPlaceObject = new MonitorObject();
details = new ArrayList<>(limit);
}
public Integer getSize()
{
int detNo=0;
synchronized (expectPlaceObject)
{
synchronized (expectItemObject) {
detNo = details.size();
}
}
return detNo;
}
public void putItem(E e) throws InterruptedException
{
synchronized (expectPlaceObject)
{
while (getSize().equals(limit)) { //ensure that we have a place
expectPlaceObject.wait(); //sleep if storage is full
}
synchronized (expectItemObject) { //there is no trouble in inners synchronized, as the second is not blocking.
details.add(e);
expectItemObject.notify(); //if anybody,who expect item, sleep, awake him.
}
}
}
public E getItem() throws InterruptedException
{
E detail;
synchronized (expectItemObject)
{
while (getSize() == 0) {
expectItemObject.wait(); //sleep if storage is empty
}
synchronized (expectPlaceObject) {
detail= details.remove(0);
expectPlaceObject.notify(); //if anybody,who expect place sleep, awake him.
}
}
return detail;
}
}
在 putItem
和 getItem
中,您正在同步两个不同的对象,expectPlaceObject
和 expectItemObject
。
问题是您在这两种方法中以不同的顺序同步它们。可能发生的情况如下:
- 线程 A 调用
putItem
并锁定expectedItemObject
- 同时线程 B 调用
getItem
并锁定expectedPlaceObject
- 接下来两个线程都想锁定另一个线程已经锁定的对象,这会导致死锁。
调查死锁的一个好方法是使用 jstack 获取进程的线程转储。输出将列出您的死锁。
尝试用这个改变你的 getSize() 方法:
public Integer getSize() {
return details.size();
}