今天做了个线程的小列子,代码如下
public class Test
{
private int x;
public void foo()
{
int current=x;
x=current+1;
}
public void go()
{
for(int i=0;i<3;i++)
{
new Thread(){
public void run(){
foo();
System.out.println(x);
}
}.start();
}
}
public static void main(String[] str)
{
new Test().go();
}
}有时会输出
2 3 2
我感觉很奇怪,想不明白其中的道理,按我自己的分析,应该是这样的...调用go()方法后会启动三个线程,三个线程都会调用foo()这个方法,foo()这个方法主要就是改变成员变量x的值,然后打印出x的值,显然,这三个线程是异步的,但是它们访问的x都是同一个成员变量呀,对于2,3,2这样的输出,按我的分析应该是这样的,首先运行的线程使x加1后就阻塞了,然后第二个线程运行时看到x已经等于1了就再加一等于2,然后其中一个阻塞,另一个打印,因为打印的都是同一个成员变量所以应该是修改后的值2没什么问题,然后第三个线程又改变x的值并打印出3(第三个线程执行时前面阻塞的那个线程应该还在阻塞不然怎么会打印3),然后阻塞的那个线程运行,按理说这时它要打印的x已经被第三个线程修改了成3了,为什么还输出2.我也考虑到了可能访问的是不同内存区的变量值,但在x前加上了 volatile 也没用呀十分困惑,请大家帮忙看看。我是哪里分析错了。为什么会打印出这样的结果
public class Test
{
private int x;
public void foo()
{
int current=x;
x=current+1;
}
public void go()
{
for(int i=0;i<3;i++)
{
new Thread(){
public void run(){
foo();
System.out.println(x);
}
}.start();
}
}
public static void main(String[] str)
{
new Test().go();
}
}有时会输出
2 3 2
我感觉很奇怪,想不明白其中的道理,按我自己的分析,应该是这样的...调用go()方法后会启动三个线程,三个线程都会调用foo()这个方法,foo()这个方法主要就是改变成员变量x的值,然后打印出x的值,显然,这三个线程是异步的,但是它们访问的x都是同一个成员变量呀,对于2,3,2这样的输出,按我的分析应该是这样的,首先运行的线程使x加1后就阻塞了,然后第二个线程运行时看到x已经等于1了就再加一等于2,然后其中一个阻塞,另一个打印,因为打印的都是同一个成员变量所以应该是修改后的值2没什么问题,然后第三个线程又改变x的值并打印出3(第三个线程执行时前面阻塞的那个线程应该还在阻塞不然怎么会打印3),然后阻塞的那个线程运行,按理说这时它要打印的x已经被第三个线程修改了成3了,为什么还输出2.我也考虑到了可能访问的是不同内存区的变量值,但在x前加上了 volatile 也没用呀十分困惑,请大家帮忙看看。我是哪里分析错了。为什么会打印出这样的结果
{
private int x;
public void foo()
{
int current=x;
x=current+1;
}
public void go()
{
for(int i=0;i<3;i++)
{
new Thread(){
public void run(){
foo();
System.out.println(x);
}
}.start();
}
}
public static void main(String[] str)
{
new Test().go();
}
}
public class Test { private int x; public void foo() {
int current = x;
x = current + 1;
} public void go() {
for (int i = 0; i < 3; i++) {
new Thread() { @Override
public void run() {
foo();
print();
}
}.start();
}
} synchronized public void print() {
System.out.println(x);
} public static void main(String[] str) {
new Test().go();
}
}
synchronized(this)
{
System.out.println(x);
}
System.ou.println(x);这句上,
加锁后,最后结果就不会比前面的小了