我写了以下代码:
public class ClassAndObjectLock {
public static void main(String[] args) {
new Thread(new EvenThread()).start();
new Thread(new OddThread()).start();
}
}
class EvenThread implements Runnable {
public void run() {
for (int i = 0; i < 10; i += 2) {
CommonClass.printEvenNumber(i);
}
}
}
class OddThread implements Runnable {
public void run() {
for (int i = 1; i < 10; i += 2) {
CommonClass.printOddNumber(i);
}
}
}
class CommonClass {
public static void printEvenNumber(int num) {
synchronized (CommonClass.class) {
System.out.println("Even :" + num);
}
}
public static void printOddNumber(int num) {
synchronized (CommonClass.class) {
System.out.println("Odd :" + num);
}
}
}
当我执行上面的代码时,输出如下:
Even :0
Odd :1
Even :2
Odd :3
Even :4
Odd :5
Even :6
Odd :7
Even :8
Odd :9
我不明白这个输出。根据我的理解,当new Thread(new EvenThread()).start();
被执行时,它会生成一个类EvenThread
的线程,该线程应获取CommonClass
的锁并保持锁定,直到它打印出全部偶数值。 OddThread
的对象只有在EvenThread
的对象完成后才有机会。因此,在我看来,输出应该如下:
Even :0
Even :2
Even :4
Even :6
Even :8
Odd :1
Odd :3
Odd :5
Odd :7
Odd :9
有人可以解释我的基本逻辑吗?
答案 0 :(得分:2)
根据我的理解,当新的Thread(new EvenThread())。start();执行后,它会生成一个类EvenThread的线程,该线程应该获取CommonClass的锁并保持锁定,直到它打印出全部偶数值。
不,事实并非如此:
public static void printOddNumber(int num) {
synchronized (CommonClass.class) {
System.out.println("Odd :" + num);
}
}
其中(由于该方法在监控类上是静态的),也可以写为
public static synchronized void printOddNumber(int num) {
System.out.println("Odd :" + num);
}
查看synchronized块的范围:它打印只有一个数字,然后释放锁。
如果你想打印所有数字而不被打断,你必须锁定整个for循环的持续时间:
public void run() {
synchronized(CommonClass.class){
for (int i = 0; i < 10; i += 2) {
System.out.println("Even :" + num);
}
}
}
答案 1 :(得分:1)
您的同步处于打印方法的级别,这意味着每个打印都会获取并释放锁定。如果您希望线程在持续时间内保持锁定,则必须在线程的run方法中同步该对象(在循环周围)。