我遇到了关于多线程编程的Java问题(请参阅下面的代码)。基于this question并在StackOverflow上回答,我想我明白为什么会出现死锁。但我不明白的是,如果程序正常工作(即没有死锁),那么foo
打印的价值是多少?我以为它会是20(thread1计数到10,thread2计数到10)。有人可以帮我解释一下这种情况(最好以一种简单的方式解释因为我还是线程编程的新手)吗?谢谢。
public class ThreadTest{
private static class ThreadOne extends Thread{
private ThreadTwo threadTwo;
public int foo = 0;
public void setThreadTwo(ThreadTwo th){
threadTwo = th;
}
public void run(){
try{
for(int i=0;i<10;i++) foo += i;
synchronized(this){this.notify();};
synchronized(threadTwo){threadTwo.wait();};
System.out.print("Foo: " + threadTwo.foo);
}catch(InterruptedException e){ e.printStackTrace();}
}
}
private static class ThreadTwo extends Thread{
private final ThreadOne threadOne;
public int foo = 0;
public ThreadTwo(ThreadOne th){
threadOne = th;
}
public void Run(){
try{
synchronized(threadOne){threadOne.wait();}
foo = threadOne.foo;
for(int i=0;i<10;i++) foo += i;
synchronized(this){this.notify();};
}
catch(InterruptedException e){e.printStackTrace();}
}
}
public static void main(){
ThreadOne th1 = new ThreadOne();
ThreadTwo th2 = new ThreadTwo(th1);
th1.setThreadTwo(th2);
th1.start(); th2.start();
th1.join(); th2.join();
}
}
答案 0 :(得分:1)
根据您的代码并且没有死锁foo
值将为90(如果我没有错误计算)。因为您foo += 1
而不是foo += i
。
foo
= 0 th1
和th2
开始。 th2
等待通知。 th1
将foo
增加到最多45 th1
通知并开始等待th2
。系统会通知th2
并开始将foo
从45增加到90 th2
通知th1
。系统会通知th1
,并打印th2.foo
,即90 编辑2:正确的方法从2个线程从0到90计数而不进行并发修改是这样的
public class ThreadTest {
private static int counter = 0;
private static class Thread1 extends Thread {
final Object lock;
public Thread1(Object lock) {
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
for (int i = 0; i < 10; i++)
counter += i;
}
}
}
private static class Thread2 extends Thread {
final Object lock;
public Thread2(Object lock) {
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
for (int i = 0; i < 10; i++)
counter += i;
}
}
}
public static void main(String[] args) {
final Object lock = new Object();
final Thread th1 = new Thread1(lock);
final Thread th2 = new Thread2(lock);
th1.start();
th2.start();
try {
th1.join();
th2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Counter: " + counter);
}
}
但是如果你被迫使用wait
和notify
,那么它会更复杂一些。使用此类的对象作为公共锁而不是对象
class Locker {
private boolean isLocked = false;
public synchronized void lock() throws InterruptedException {
while (isLocked) wait();
isLocked = true;
}
public synchronized void unlock() {
isLocked = false;
notify();
}
}
在run
方法中,我们喜欢这样:
@Override
public void run() {
try {
locker.lock();
for (int i = 0; i < 10; i++)
counter += i;
locker.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}