提问人:JASON CHAN 提问时间:10/22/2023 最后编辑:Mark RotteveelJASON CHAN 更新时间:10/22/2023 访问量:50
为什么使用Integer进行计算时会导致死锁?[复制]
why does it cause deadlock when I use Integer to computation? [duplicate]
问:
我正在尝试解决称为穿越单板桥的问题。以下是问题的描述:
有一座单板桥。只有一个人可以过桥 没有任何停止。行人可以从西边过桥 向东或从东向西。如果人行横道超过 0 个 这座桥从西向东,没有行人可以尝试过 从东到西的桥,但超过1名行人可以过桥 从西向东桥,反之亦然。行人可以过马路 如果桥上没有行人,请立即上桥。用 信号量来解决这个问题。
如果我使用 Integer,某个时候会发生死锁。当发生死锁时,wait semaphore、leftCnt 和 westCnt 的值为 0,但当 leftCnt 或 westCnt 等于零时,它会释放 wait 信号量。 但是,如果我使用 MyInt,一切都会顺利进行。
我的解决方案如下:
import java.util.concurrent.Semaphore;
//person from east to west
public class Task1 implements Runnable{
Semaphore east, west, wait;
// MyInt westCnt, eastCnt;
// public Task1(Semaphore east, Semaphore west, Semaphore wait, MyInt westCnt, MyInt eastCnt) {
// this.east = east;
// this.west = west;
// this.wait = wait;
// this.westCnt = westCnt;
// this.eastCnt = eastCnt;
// }
Integer westCnt, eastCnt;
public Task1(Semaphore east, Semaphore west, Semaphore wait, Integer westCnt, Integer eastCnt) {
this.east = east;
this.west = west;
this.wait = wait;
this.westCnt = westCnt;
this.eastCnt = eastCnt;
}
@Override
public void run() {
try {
east.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
// eastCnt.inc();
// if(eastCnt.getInteger() == 1) {
// try {
// wait.acquire();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
eastCnt++;
if(eastCnt.equals(1)) {
try {
wait.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("E -> W, on bridge");
east.release();
try {
east.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("E -> W, finish");
// eastCnt.dec();
// if(eastCnt.getInteger() == 0)
// wait.release();
eastCnt--;
if(eastCnt.equals(0))
wait.release();
east.release();
}
}
import java.util.concurrent.Semaphore;
//person from west to east
public class Task2 implements Runnable{
Semaphore east, west, wait;
// MyInt westCnt, eastCnt;
// public Task2(Semaphore east, Semaphore west, Semaphore wait, MyInt westCnt, MyInt eastCnt) {
// this.east = east;
// this.west = west;
// this.wait = wait;
// this.westCnt = westCnt;
// this.eastCnt = eastCnt;
// }
Integer westCnt, eastCnt;
public Task2(Semaphore east, Semaphore west, Semaphore wait, Integer westCnt, Integer eastCnt) {
this.east = east;
this.west = west;
this.wait = wait;
this.westCnt = westCnt;
this.eastCnt = eastCnt;
}
@Override
public void run() {
try {
west.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
// westCnt.inc();
// if(westCnt.getInteger() == 1) {
// try {
// wait.acquire();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
westCnt++;
if(westCnt.equals(1)) {
try {
wait.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("W -> E, on bridge");
west.release();
try {
west.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("W -> E, finish");
// westCnt.dec();
// if (westCnt.getInteger() == 0)
// wait.release();
westCnt--;
if(westCnt.equals(0))
wait.release();
west.release();
}
}
//test
public class TestApplication {
public static void main(String args[]) {
Semaphore east = new Semaphore(1);
Semaphore west = new Semaphore(1);
Semaphore wait = new Semaphore(1);
// MyInt eastInt = new MyInt();
// MyInt westInt = new MyInt();
Integer eastInt = 0;
Integer westInt = 0;
List<Thread> list1 = new ArrayList<>();
List<Thread> list2 = new ArrayList<>();
for (int i = 0; i < 100; i++) {
list1.add(new Thread(new Task1(east,west,wait, eastInt, westInt)));
list2.add(new Thread(new Task2(east,west,wait,eastInt, westInt)));
}
for (int i = 0; i < list1.size(); i++) {
list1.get(i).start();
list2.get(i).start();
}
}
}
public class MyInt {
private int integer = 0;
public void setInteger(int integer) {
this.integer = integer;
}
public int getInteger() {
return integer;
}
public void inc(){
integer++;
}
public void dec(){
integer--;
}
}
答:
0赞
Elliott Frisch
10/22/2023
#1
Integer
是不可变的,因此每次值更改时,您都有一个不同的实例(根据定义)。使用 AtomicInteger
而不是重新发明它。
评论
0赞
JASON CHAN
10/22/2023
明白了。感谢您的回复。
评论