多线程同步问题,[附简单代码]
Java code
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
------解决方案--------------------关注,是挺神气的....也许x++,和y++在运行的时候不是顺序执行的?期待高手解答.
------解决方案--------------------因为你的使用的是同一个violentObject 对象,两个线程同时改变这个y值,
------解决方案--------------------x++ => tmp = x + 1; //A
x = tmp; //B
当Thread1执行完A后,Thread2开始执行,假设此时x=30。
Thread2执行一段时间后,x=100, y=100,此时Thread1继续,执行B,此时tmp=31。于是出现了y > x。
------解决方案--------------------ls的...两个线程他也是先到x在到y啊.
------解决方案--------------------刚才说的lss,ls的我看了.似乎想起来看corejava的时候说过java很多操作不比如i++不是原子操作.是分两步的..所以多线程的时候可能会有不可预期的结果.
------解决方案--------------------加锁并且同步,问题还的存在,只是数据的误差没有你的这个大,只是到了一定的时候才会发现数据存在误差,但是之后又回复一致,也就是x和y的值相等,我想,这个是虚拟机调度线程是不确定的,因为你的把一个线程休眠了500毫秒,再让其复活,到底是谁进入runnable状态,还得等虚拟机来分配,这个分配是根据级别和当前的等待状态来决定,及时你的线程进入了runnable状态,也不一定得到run,这就是虚拟机调度线程的时候存在的不确定性.
------解决方案--------------------这是由于,你的ViolentObject类所对应的对象,不是线程安全的,而造成的。
如果将ViolentObject的两个方法都添加Synchronized关键字,就可以x与y的值相等。
出现这种状况(x>y),具有随机性。
我们知道,对一个变量做++运算的时候,这个变量会先从内存中读取到CPU的寄存器当中,++运算后,再将寄存器的值,回写到内存当中。
那么,在多线程对同一变量做++运算的时候,会出现数据的不同步现象。
我们知道,线程在操作系统中,是按照时间片来运行的。
如果线程1,刚把x变量,从内存中读到寄存器中,这时,时间片用完了,之后,线程2运行,把x从内存中读到寄存器,完成++运算,又回写到内存,
这样,当线程1重新获得时间片,继续刚才的++操作,然后再回写到内存,
此时,2个线程都对x做了++运算,
但是,由于两次从内存取值都是相同的所以,结果,相当于只完成了一次运算。
由于上述现象的产生具有不确定性,所以,两个变量x、y,它们的大小,也具有不确定性。
使用synchronized关键字,就会将相对应的对象上锁,当操作线程没有是放对应的锁时,其他线程是不可能访问的。
楼主还可以试一试,将x、y两个变量,在声明的时候,都添加volatile关键字,效果,可能要不什么都不加要好。
但是,添加volatile关键字的方法,无法保证在输出结果是x与y相同的值,
因为每次对两个变量都是++操作,那么,输出x与y的差值应该不超过4.
当然,不超过4只是我的理论推测,楼主有兴趣,可以试一下。
哈哈。
------解决方案--------------------回帖是一种美德!
------解决方案--------------------总共是3个线程在运行.
因为存取的是同一个对象,
System.out.println("x="+x+","+"y="+y)这条语句