读书人

线程同步错误分析

发布时间: 2013-01-25 15:55:29 作者: rapoo

线程同步异常分析

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

什么?你不相信?

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

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即可实现。


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

读书人网 >编程

热点推荐