首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

线程同步错误分析

2013-01-25 
线程同步异常分析当我们用多个线程去取得同一个对象中的某一个属性时,可能会出错,原因是很可能有一个或多

线程同步异常分析

当我们用多个线程去取得同一个对象中的某一个属性时,可能会出错,原因是很可能有一个或多个线程在同一时间去获取它。这是很危险的,好比对象就是一个银行账户,而属性就是该银行账户中的资金数目,当多个人对该账户同时取钱时,如果不采取措施,很可能会出现重复取钱事件。当然,从一方面来说,出现这样的问题,得益的是我们广大普通老百姓,但是,显然我们的国家并不希望这样的事情屡次发生。即使发生了,钱也不是你的。所以,为了防止类似“许霆案”的案件发生,有必要对这个问题进行解决。

什么?你不相信?

小二,上代码!(好嘞~新鲜热乎的代码)

packagecode;

 

/**

 *分析线程同步中的异常及解决办法

 *

 *@authorAndre

 *

 */

 

publicclass Test {

 

        /**

          *获得实现了Runnable接口的对象

          *

          *@paramstr

          */

        publicRunnable getRunnable(String str) {

                   str="code." + str;

                   Runnablerb =null;

                  try{

                            rb= (Runnable) Class.forName(str).newInstance();

                   }catch (InstantiationException e) {

                            e.printStackTrace();

                   }catch (IllegalAccessException e) {

                            e.printStackTrace();

                   }catch (ClassNotFoundException e) {

                            e.printStackTrace();

                   }

                  returnrb;

 

         }

 

        /**

          *让线程并发执行

          */

        publicvoid runInGroup(Runnable rb, intn) {

                  for(int i = 0; i < n; i++) {

                            Threadtr =new Thread(rb);

                            tr.start();

 

                   }

         }

 

        publicstaticvoidmain(String[] args) {

                   Testtest =new Test();

 

                  //根据名称获取实现了Runnable接口的对象

                   Runnablerb = test.getRunnable("Plus2");

                  //启动线程

                   test.runInGroup(rb,40000);

 

         }

}

 

Plus1类:即对操作不进行任何限制的

packagecode;

 

/**

 *不进行任何同步措施

 *

 *@authorAndre

 *

 */

publicclass Plus1 implementsRunnable {

 

        privatelongnum= 0;

 

        publicvoid run() {

                   add();

         }

 

        publicvoid add() {

                  //对num进行一百次加加操作

                  for(int i = 0; i < 100; i++) {

                           num++;

                           //每隔1000输出一次

                           if(num % 1000 == 0) {

                                     System.out.println(" i =" +num);

                            }

                   }

         }

}

 


问题分析:

可能你期待的结果是这样的……线程同步错误分析课运行后,你得到的结果却是:线程同步错误分析

少加了几千个数!!!

当然啦,原因已经分析过了,即多个线程同时对一个对象的某个属性操作时,比如A,B线程同时获取到的是100,加上1以后,变成101,100经过两个线程调用add()方法后变成101。

解决办法:

解决的办法有    1.对add()方法加同步关键字synchronic

2.对关键代码段加锁

3.创建原子性的属性

 

一个一个来看

Plus2类:对add()方法加同步关键字synchronic

publicsynchronizedvoid add()

这样就可以保证同一时间只有一个线程在调用add()方法

 

Plus3类:对关键代码段加锁

先创建一个Object类对象,private char[] lockObj = new char[1];

再对代码段加上锁

synchronized (lockObj){

                    for(int i = 0; i < 100; i++) {

                           num++;

                           //每隔1000输出一次

                           if(num % 1000 == 0) {

                                   System.out.println(" i =" +num);

                            }

                     }

}

这样每个线程都要获取到钥匙后才能打开锁,保证了实时性。

 

Plus4类:创建 原子性 的属性

所谓原子性,表面上理解就是 不可分割的。我们写的高级语言其实都要转化为机器指令才能被计算机执行,而在机器指令中,一个“i++”操作由:取值放到寄存器中、加一、放回内存三条机器指令组成。而线程不同步会出错的原因也在于此!

那么,只需要调用Java中的一个类 java.util.concurrent.atomic.AtomicLong即可实现。


线程同步异常问题分析到此为止!谢谢观看!

 

 

 

 

 

热点排行