精华帖 (0) :: 良好帖 (1) :: 新手帖 (4) :: 隐藏帖 (3)
|
|
---|---|
作者 | 正文 |
发表时间:2010-04-24
最后修改:2010-04-25
以下为测试代码,通过一个自增函数得到最新的值,玩Set你存,看是否有重复。如果递增式原子性的者这个函数不会出错
package com.woxiaoe.study.thread; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 验证Java中递增操作不是递增的 * @author 小e * * 2010-4-24 下午09:53:50 */ public class SerialNumberChecker { private static Set<Integer> serialNumberSet = new HashSet<Integer>(); static int base = 0; static int THREAD_SIZE = 10; static class SerialChecker implements Runnable{ private SerialNumberChecker snc; public SerialChecker(SerialNumberChecker snc) { this.snc = snc; } @Override public void run() { while(true){ //int number = snc.nextNumber(); int number = snc.base ++; if(serialNumberSet.contains(number)){ System.out.println("存在重复值:" + number); System.exit(0); }else{ serialNumberSet.add(number); } } } } public static void main(String[] args) { ExecutorService exec = Executors.newCachedThreadPool(); SerialNumberChecker snc = new SerialNumberChecker(); for(int i = 0; i < THREAD_SIZE; i++){ exec.execute(new SerialChecker(snc)); } } } Output: 存在重复值:26202 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-04-25
这不能证明递增不是原子性的,只能证明你那个函数不是线程安全的。即使++是原子性的,这个例子也还可能出现你描述的情况。问题是当++完成后,在函数返回前,如果另外一个线程也进入了,然后++了那个变量,然后第一个线程又激活,返回了这个被修改的值,则2个线程返回的值就会相同。
|
|
返回顶楼 | |
发表时间:2010-04-25
wumingshi 写道
这不能证明递增不是原子性的,只能证明你那个函数不是线程安全的。即使++是原子性的,这个例子也还可能出现你描述的情况。问题是当++完成后,在函数返回前,如果另外一个线程也进入了,然后++了那个变量,然后第一个线程又激活,返回了这个被修改的值,则2个线程返回的值就会相同。
嗯那样是不严谨,但是java中递增的确不是原子性,我们可以把代码改一下,不调用方法 package com.woxiaoe.study.thread; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 验证Java中递增操作不是递增的 * @author 小e * * 2010-4-24 下午09:53:50 */ public class SerialNumberChecker { private static Set<Integer> serialNumberSet = new HashSet<Integer>(); public static int base = 0; public static int THREAD_SIZE = 10; public static int nextNumber(){ return ++ base; } static class SerialChecker implements Runnable{ private SerialNumberChecker snc; public SerialChecker(SerialNumberChecker snc) { this.snc = snc; } @Override public void run() { while(true){ //int number = snc.nextNumber(); int number = snc.base ++; if(serialNumberSet.contains(number)){ System.out.println("存在重复值:" + number); System.exit(0); }else{ serialNumberSet.add(number); } } } } public static void main(String[] args) { ExecutorService exec = Executors.newCachedThreadPool(); SerialNumberChecker snc = new SerialNumberChecker(); for(int i = 0; i < THREAD_SIZE; i++){ exec.execute(new SerialChecker(snc)); } } } Output: 存在重复值:4843 // 还是有重复值的 |
|
返回顶楼 | |
发表时间:2010-04-25
java 的自增自减都不是原子的。。如果要用原子的可以用原子类来做。Java api 上面可找到
|
|
返回顶楼 | |
发表时间:2010-04-25
最后修改:2010-04-25
建议lz仔细去阅读一下编译原理。或者使用 atominteger
|
|
返回顶楼 | |
发表时间:2010-04-25
最后修改:2010-04-25
NetBus 写道 建议lz仔细去阅读一下编译原理。或者使用 atominteger
呵呵,我的本意是展示这个现象。当然atominteger是一个解决方案。 |
|
返回顶楼 | |
发表时间:2010-04-25
Java自增是原子操作,但是通过函数返回就不是原子操作了。
++ base是原子操作,但是return ++ base;就不是了。 |
|
返回顶楼 | |
发表时间:2010-04-25
haole 写道 Java自增是原子操作,但是通过函数返回就不是原子操作了。
++ base是原子操作,但是return ++ base;就不是了。 别逗了。 |
|
返回顶楼 | |
发表时间:2010-04-25
zhxing 写道 java 的自增自减都不是原子的。。如果要用原子的可以用原子类来做。Java api 上面可找到
嗯 谢谢 嘿嘿我也刚看过了 lz也看看吧 |
|
返回顶楼 | |
发表时间:2010-04-25
whaosoft 写道 zhxing 写道 java 的自增自减都不是原子的。。如果要用原子的可以用原子类来做。Java api 上面可找到
嗯 谢谢 嘿嘿我也刚看过了 lz也看看吧 java编程思想里面有讲 |
|
返回顶楼 | |