package thread;
public class SyncTest implements Runnable {
/**
* 深入理解多线程。
* @param args
*/
private int x;
private int y;
public void run(){
synchronized(this){
x++;
y++;
}
System.out.println(Thread.currentThread().getName()+",x="+x+",y="+y);//注意此打印语句不在同步块中。
}
// 下面是几种输出结果
// Thread-1,x=2,y=2
// Thread-0,x=1,y=2
// Thread-1,x=2,y=2
// Thread-0,x=2,y=2
// Thread-1,x=2,y=2
// Thread-0,x=1,y=1
public static void main(String[] args) {
// TODO Auto-generated method stub
SyncTest that=new SyncTest();
new Thread(that).start();
new Thread(that).start();
}
}
不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;
如果上面的二句话正确的话,现在又有了不同的疑问:被synchronized修饰的代码块能在没执行完的情况下跳出??怎么会出现第一种结果?
------解决方案--------------------------------------------------------
我这里打印出来的结果是
Thread-0,x=1,y=1
Thread-1,x=2,y=2
但是我觉得如果不把输出语句放入同步块的话应该几种可能都有,第一个线程的输出语句和第二个进入同步块的线程在竞速
------解决方案--------------------------------------------------------
首先LZ要明白,synchronized是为了多线程对同一个共享资源同步而采取的控制措施,如果不是同一个资源,互相之间不存在任何干涉,当然就没可以同时访问了。
简单的举例,A,B两个线程,如果同时访问C,那么当A调用C的synchronized方法时,B就不能调用该方法,要等待,而如果B不去调用C,而是去掉用D的synchronized方法,因为C和D不相干,所以B当然能调用了
出现这种结果,是因为打印和累加不同步,也就是打印没在synchronized里面
简单的分析
第一个线程进入synchronized,进行x++,y++,执行后x=1,y=1,然后synchronized结束,然后进行打印,因为打印的参数是个字符串计算式,所以先求出字符串结果,Thread.currentThread().getName()+",x="+x+",y="+y,当字符串进行到+y前(注1),系统把CPU收回,分配给第二个线程(这时第一个线程停止了),然后第二个线程进入synchronized,进行x++,y++,此时x=2,y=2,然后顺利打印结束后,系统把CPU又分配给第一个线程,于是第一个线程从注1处开始继续执行+y(此时y已经是2),所以就得出输出的结果
------解决方案--------------------------------------------------------
呵呵。。稍微改变一下,LZ就都明白了。
public void run(){
synchronized(this){
x++;
y++;
System.out.println(Thread.currentThread().getName()+",x="+x+",y="+y);//注意此打印语句不在
}
}