今天在学习多线程的时候遇到了一个问题:使用同步锁执行count++时,锁对象为this,执行结果却还是有重复。代码如下:
public class MethodTest2 {
private static int count = 0;
public static void main(String[] args) {
//创建Thread对象并重写run方法
new Thread() {
@Override
public void run() {
while(count < 100) {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + "执行,count:" + count ++);
}
}
}
}.start();
//创建Thread对象并传入一个实现Runnable接口的匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
while(count < 100) {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + "执行,count:" + count ++);
}
}
}
}).start();
}
}
程序运行结果部分如下:
可见,执行结果并没有按照count顺序执行。若更换锁对象为字符串常量 “123” (内存中只有一个),执行结果就会正确。这让我觉得可能是因为两个this不是同一个对象,所以简化了代码,打印两个this。代码如下:
public class MethodTest {
public static void main(String[] args) {
//创建Thread对象并重写run方法
new Thread() {
@Override
public void run() {
System.out.println("new Thread:" + this);
}
}.start();
//创建Thread对象并传入一个实现Runnable接口的匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("new Runnable:" + this);
}
}).start();
}
}
上述代码打印的结果如下:
第一个this打印的是:Thread[Thread-0,5,main]
而第二个this打印的却是:com.hu.test.MethodTest$2@11af0a8d
可见两个this并不是同一个对象。在经过分析之后终于找到原因:第一个this代指的是主类MethodTest的一个匿名内部类,这个内部类继承自Thread类,并重写了run方法,其中Thread类重写了toString方法。只是没有声明引用指向这个对象,而是直接调用了它的start方法。第二个this代指的是主类MethodTest的另一个匿名内部类,这个内部类实现了Runnable接口,并重写了run方法。它们两个this代指的是不同的对象。