public class ViolentAccessDemo
{
public static void main(String args[])
{
ViolentObject violentObject = new ViolentObject();
Thread thread1 = new Thread(new ThreadAccess(violentObject));
Thread thread2 = new Thread(new ThreadAccess(violentObject));
thread1.start();
thread2.start();
for(int i=0;i<10;i++)
{
violentObject.print();
try{
Thread.sleep(500);
}catch(InterruptedException e)
{
}
}
}
}
class ViolentObject
{
private int x;
private int y;
public void increase()
{
x++; //我的理解是thread1执行到x++;没有执行y++退出。
y++; //thread2接着还是执行x++,这样的话,输出x的值肯定是x大才对,可是输出结果:
}
public void print()
{
System.out.println("x="+x+","+"y="+y);
}
}
class ThreadAccess implements Runnable
{
private ViolentObject violentObject;
public ThreadAccess(ViolentObject vob)
{
System.out.println("this is constructor of ThreadAccess");
this.violentObject = vob;
}
public void run()
{
while(true) violentObject.increase();
}
}
输出结果:
this is constructor of ThreadAccess
this is constructor of ThreadAccess
x=0,y=0
x=84050630,y=89506803 //y居然比x大,这不违反规律了吗?
x=165934856,y=166907497
x=250595453,y=257923836
x=336504131,y=328009964
x=432364945,y=416151003
{
public static void main(String args[])
{
ViolentObject violentObject = new ViolentObject();
Thread thread1 = new Thread(new ThreadAccess(violentObject));
Thread thread2 = new Thread(new ThreadAccess(violentObject));
thread1.start();
thread2.start();
for(int i=0;i<10;i++)
{
violentObject.print();
try{
Thread.sleep(500);
}catch(InterruptedException e)
{
}
}
}
}
class ViolentObject
{
private int x;
private int y;
public void increase()
{
x++; //我的理解是thread1执行到x++;没有执行y++退出。
y++; //thread2接着还是执行x++,这样的话,输出x的值肯定是x大才对,可是输出结果:
}
public void print()
{
System.out.println("x="+x+","+"y="+y);
}
}
class ThreadAccess implements Runnable
{
private ViolentObject violentObject;
public ThreadAccess(ViolentObject vob)
{
System.out.println("this is constructor of ThreadAccess");
this.violentObject = vob;
}
public void run()
{
while(true) violentObject.increase();
}
}
输出结果:
this is constructor of ThreadAccess
this is constructor of ThreadAccess
x=0,y=0
x=84050630,y=89506803 //y居然比x大,这不违反规律了吗?
x=165934856,y=166907497
x=250595453,y=257923836
x=336504131,y=328009964
x=432364945,y=416151003
x = tmp; //B当Thread1执行完A后,Thread2开始执行,假设此时x=30。
Thread2执行一段时间后,x=100, y=100,此时Thread1继续,执行B,此时tmp=31。于是出现了y > x。
这样,当线程1重新获得时间片,继续刚才的++操作,然后再回写到内存,
此时,2个线程都对x做了++运算,
但是,由于两次从内存取值都是相同的所以,结果,相当于只完成了一次运算。由于上述现象的产生具有不确定性,所以,两个变量x、y,它们的大小,也具有不确定性。使用synchronized关键字,就会将相对应的对象上锁,当操作线程没有是放对应的锁时,其他线程是不可能访问的。楼主还可以试一试,将x、y两个变量,在声明的时候,都添加volatile关键字,效果,可能要不什么都不加要好。
但是,添加volatile关键字的方法,无法保证在输出结果是x与y相同的值,
因为每次对两个变量都是++操作,那么,输出x与y的差值应该不超过4.
当然,不超过4只是我的理论推测,楼主有兴趣,可以试一下。哈哈。
不过,我研究了下,还是觉得JAVA是按行解释执行的。
不可能y会执行得比x多
因为存取的是同一个对象,
System.out.println("x="+x+","+"y="+y)这条语句
main线程输出x和y的值之间有个时间差,在此期间另外两个线程仍然在进行++操作.
所以当打印y的值时就比x大了.
y++;
这里的x和y值的更新次序是存在颠倒的可能的。加上volatile关键字就可以保证j的值永远不会大于i的值。
不错 谢谢
顶一下.谢谢.
回帖是一种美德!
UP
UP
努力的学习学习!!!期待该问题的发展。
好东西啊,我顶
顶顶
好用么?先下下来看看。这种精神值得学习。
多谢了,学下先。
while (true){
synchronized(violentObject){
violentObject.increase();
}
}
}
然后按你的测试。发现1:x 2
2:x 2
1:y 1
2:y 2
1:x 3
1:y 3
2:x 4
2:y 4
1:x 5
2:x 5
2:y 6
1:y 5
1:x 6
2:x 7
2:y 7
1:y 8
2:x 8
2:y 9
1:x 8
1:y 10
2:x 10
2:y 11
1:x 10
1:y 12
2:x 11
2:y 13
1:x 12
1:y 14
1:x 13
1:y 15
main over.
2:x 14
2:y 16很显然。进行到4~5秒的时候。俩线程开始混运行了。
引用中说的安全性很重要。如果不能确保对象的同步性,就尽量不要用多线程。
Thread thread2 = new Thread(new ThreadAccess(violentObject));
thread1.start();
thread2.start();
启动了线程, 以后就由操作系统按照自己的理解运行它了。
你不能因为是
thread1.start();
thread2.start(); 就要求OS先运行thread1再运行thread2。
thread1.start();
thread2.start();
跟
thread2.start();
thread1.start();
都是一样的结果(都混乱)。java里用 Synchronized关键字来完成线程的同步。
VC里面常用 EVENT配合WaitForSingleObject()函数来达到同步效果。
因为存取的是同一个对象,
System.out.println("x="+x+","+"y="+y)这条语句
main线程输出x和y的值之间有个时间差,在此期间另外两个线程仍然在进行++操作.
所以当打印y的值时就比x大了.