关于JAVA的同步试验

虽然搞JAVA好多年,一直没有搞明白同步Serializable,闲来无事,做几个小程序测试一下多线程计算一个静态数:

 

下面的代码是我经过修改后的最终版代码。

 

先创建一个Persons ,用了单例模式,SET和GET方法都做了Serializable,输出方法放在单例的Person里并且做了同步,无论如何限制get方法都会有输出重复的问题,但是有一个现象,就是尽管数据有重复,但是所有的重复后就会跳过重复的数,如1,2,2,4这样的效果,最后我分析,只要程序做了单例,计算的方法是有Serializable的,其实这个变量都是递增的,之所以取出来的数据会重复,完全是因为取数据的方法取的是对象内存变量,而在多线程执行的时候,一个对象的存和取并不是同步的。

  

/**
 * @author huang.yueyong
 * @date   2010-8-15
 *
 */
package test;

import java.io.Serializable;

/**
 * @author huangyy
 *
 */
public class Persons implements Serializable{
  int flag=0;
 private static Persons instant=null;
 
    private Persons(){
  
 }  
 /**
  * @return the flag
  */
 public synchronized int getFlag() {  
  return this.flag;
 }

// /**
//  * @param flag the flag to set


//  */
 public synchronized void setFlag(int flag) {
  System.out.println("输入Flag:"+flag);
  this.flag = flag;
 }

 public static Persons getPerson(){
     if(instant==null){
   instant=new Persons();
   System.out.println("Person init!");
  }
     return instant;
    }

}

 

/**
 * @author huang.yueyong
 * @date   2010-8-13
 *
 */
package test;

/**
 * @author huangyy
 *
 */
public class Thread1 implements Runnable { 
 /**
  * @param args
  */

 public void run() {
 
  while(true){
   Persons per=Persons.getPerson(); 
   per.setFlag(per.getFlag()+1);
   System.out.println("线程1:"+per.getFlag());
   
   try {
    Thread.sleep(1*10);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }  
 } 
}

/**
 * @author huang.yueyong
 * @date   2010-8-13
 *
 */
package test;

/**
 * @author huangyy
 *
 */
public class Thread2 implements Runnable {

 /**
  * @param args
  */

 public static void main(String[] args){

  Thread1 st1=new Thread1();
  Thread2 st2=new Thread2();
  Thread tr1=new Thread(st1);
  Thread tr2=new Thread(st2);
  tr1.start();
  tr2.start();

 }

 public void run() {
  Persons per=Persons.getPerson(); 
  while(true){
   if(per.getFlag()>100){
    System.exit(0);
   }    
   per.setFlag(per.getFlag()+1);
   System.out.println("线程2:"+per.getFlag());
   
   try {
    Thread.sleep(1*10);    
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
}
}

 

用这个测试方法,发现单看输入的值一直都是正确的,可是输出时候虽然做了同步,但是取出来的数据仍然会有重复的情况,说明同步其实主要是针对方法而言,针对对象的同步其实没有多大的实际意义。

 

这个实验告诉我,我们在对变量计算的时候,如果确实需要同步,业务直接在这一个方法里完成,如果用到其它方法,需要在这个方法里,把变量当参数传出去,不要指望这个对像为你保存场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值