话不多,直接上代码,去年刚学java时发现的一个问题,现在看起来居然还懵了一会,所以记录下
public class TestSynconnized {
private Object object = new Object();
private volatile Integer i = 0;
public void Add() {
synchronized(i) {
System.out.println("++i="+(++i)+Thread.currentThread().getName());
}
}
public static void main(String args[]) {
TestSynconnized testSynconnized = new TestSynconnized();
for (int i = 0; i < 20; i++) {
Thread thread = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
testSynconnized.Add();
}
}
});
thread.start();
}
while (Thread.activeCount() > 1) {
Thread.yield();
}
System.out.println(testSynconnized.i);
}
}
运行这段代码发现并不是每次执行的结果都是20000,原因:在同步方法块中更新了锁对象,导致锁失效。
在执行i++并退出同步方法块后,另一个持有原先的i对象锁的线程进入同步方法块。此时下一个线程运行到synchronized时锁条件已经变化,也可进入同步方法块,再次感谢知乎网友meantobe的解答,直接复制了答案
修改方法
public class TestSynconnized {
private Object object = new Object();
private volatile Integer i = 0;
public synchronized void Add() {
{
System.out.println("++i="+(++i)+Thread.currentThread().getName());
}
}
public static void main(String args[]) {
TestSynconnized testSynconnized = new TestSynconnized();
for (int i = 0; i < 20; i++) {
Thread thread = new Thread(()-> {
for (int j = 0; j < 1000; j++) {
testSynconnized.Add();
}
}
);
thread.start();
}
while (Thread.activeCount() > 1) {
Thread.yield();
}
System.out.println(testSynconnized.i);
}
}
这段代码实际是从深入理解java虚拟机里面捞出来改的
网友评论