JDK说明:
public class AtomicLong
extends Number
implements Serializable
可以用原子方式更新的 long 值。有关原子变量属性的描述,请参阅 java.util.concurrent.atomic 包规范。AtomicLong 可用在应用程序中(如以原子方式增加的序列号),并且不能用于替换 Long。但是,此类确实扩展了 Number,允许那些处理基于数字类的工具和实用工具进行统一访问。AtomicLong是原子的,Long不是原子操作的。

解决方案 »

  1.   


    这个我也看到了,但是说AtomicInteger这个类,既然是原子操作的类,那么,为什么set方法没有同步,我也写了个测试,发现int赋值确实不是原子操作,我就更加不明白为什么Atomic的set方法不同步了。这个是代码,这样测试,发现确实是有问题的,总会走到System.err这里。public class Test {
    public static void main(String[] args) throws Exception {
    Run r = new Run();
    for (int i = 0; i < 10; i++)
    new Thread(r).start();
    }
    }class Run implements Runnable { static final int MIN = 0; static final int MAX = 2000000000; // 这里加不加volatile都是一样的结果。
    volatile int num = MIN; @Override
    public void run() {
    // 变量num就始终就两个取值,MIN和MAX,在这两个值之间来回赋值。
    // 如果发现num即不是MIN、也不是MAX,
    // 就会走到System.err输出这行代码,
    // 那么就说明有某个线程读取到了一个错误的值。
    for (int i = 0; i < 999999; i++) {
    if (num != MIN && num != MAX) {
    System.err.println("!!! ");
    return;
    }
    num = MAX;
    num = MIN; }
    }
    }
    改成这样,加上同步,就没问题了,不会走到System.err这里。public class Test {
    public static void main(String[] args) throws Exception {
    Run r = new Run();
    for (int i = 0; i < 10; i++)
    new Thread(r).start();
    }
    }class Run implements Runnable { static final int MIN = 0; static final int MAX = 2000000000; // 这里加不加volatile都是一样的结果。
    volatile int num = MIN; @Override
    public void run() {
    // 变量num就始终就两个取值,MIN和MAX,在这两个值之间来回赋值。
    // 如果发现num即不是MIN、也不是MAX,
    // 就会走到System.err输出这行代码,
    // 那么就说明有某个线程读取到了一个错误的值。
    for (int i = 0; i < 999999; i++) {
    synchronized (this) {
    if (num != MIN && num != MAX) {
    System.err.println("!!! ");
    return;
    }
    num = MAX;
    num = MIN;
    }
    }
    }
    }
      

  2.   

    int 赋值怎么不是原子的。不同步的是代码块
      

  3.   

    http://blog.csdn.net/liujinwei2005/article/details/6295666
      

  4.   


    感谢您的回复,还打扰您一下。
    您说的我也考虑过,但我后来又觉得,既然说int赋值是原子性到的,原子不是说是不可拆分的吗,我理解的是,赋值过程中,还没结束,就能被其它线程读取到,应该不算原子操作了吧?就像上面代码里一样,if读到了一个异常值,既不是MAX也不是MIN。
    如果还要代码块同步才能得到正确结果,那这个int赋值应该算不上是原子操作呀。
      

  5.   

    AtomicLong.set(long newValue)非原子操作!
    AtomicLong.compareAndSet(long expect, long update)原子操作!通常改变原子类的值都用第二个方法,第一个方法一般是初始化!第二个方法什么意思应该很明了
    compareandswap
      

  6.   

    另外说明一点,原子类的同步不是采用synchronized 的方式,所以你在源码是看不到synchronized 的!原子包是1.5以后的新特性!这种同步方式优于synchronized !AtomicLong.compareAndSet(long expect, long update)这个方法转译成字节码后只有一个语句!
      

  7.   


    感谢您的回复,还打扰您一下。
    您说的我也考虑过,但我后来又觉得,既然说int赋值是原子性到的,原子不是说是不可拆分的吗,我理解的是,赋值过程中,还没结束,就能被其它线程读取到,应该不算原子操作了吧?就像上面代码里一样,if读到了一个异常值,既不是MAX也不是MIN。
    如果还要代码块同步才能得到正确结果,那这个int赋值应该算不上是原子操作呀。
    int赋值竟然是原子的,尼玛,小伙伴们都惊呆了,不知道这四颗红星怎么得来的
      

  8.   


    感谢您的回复,还打扰您一下。
    您说的我也考虑过,但我后来又觉得,既然说int赋值是原子性到的,原子不是说是不可拆分的吗,我理解的是,赋值过程中,还没结束,就能被其它线程读取到,应该不算原子操作了吧?就像上面代码里一样,if读到了一个异常值,既不是MAX也不是MIN。
    如果还要代码块同步才能得到正确结果,那这个int赋值应该算不上是原子操作呀。
    int赋值竟然是原子的,尼玛,小伙伴们都惊呆了,不知道这四颗红星怎么得来的什么是原子????????
      

  9.   


    Google java 原子操作 基本类型 赋值
    https://www.google.com/search?num=20&newwindow=1&q=java+%E5%8E%9F%E5%AD%90%E6%93%8D%E4%BD%9C+%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B+%E8%B5%8B%E5%80%BC+&oq=java+%E5%8E%9F%E5%AD%90%E6%93%8D%E4%BD%9C+%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B+%E8%B5%8B%E5%80%BC
    http://blog.csdn.net/yuanwofei/article/details/12843591
      

  10.   


    答非所问,竟说一些,对方知道的老掉牙的事情。你Y 有病吧,你Y以为自己是陈冠希?张柏芝?还是杨幂薛凯琪啊。
    你这样狗嘴里吐不出象牙来你妈知道吗?
    你脑子豆腐渣做的吗?你爸妈知道吗?你是只狗,结果你吐出了象牙,你是狗跟大象杂交的是吧。
    那你就是连猪狗不如了,我哪里招你惹你了。
    就算我没有解答楼主的问题,你也用不着到处乱咬人吧,况且这里本来就是技术交流区,大家各抒己见而已。
    真不知道你爸妈怎么教育的你,真替你爸妈丢人!
    答非所问,竟说一些,对方知道的老掉牙的事情。你Y 有病吧,你Y以为自己是陈冠希?张柏芝?还是杨幂薛凯琪啊。
    你这样狗嘴里吐不出象牙来你妈知道吗?
    你脑子豆腐渣做的吗?你爸妈知道吗?你是只狗,结果你吐出了象牙,你是狗跟大象杂交的是吧。
    那你就是连猪狗不如了,我哪里招你惹你了。
    就算我没有解答楼主的问题,你也用不着到处乱咬人吧,况且这里本来就是技术交流区,大家各抒己见而已。
    真不知道你爸妈怎么教育的你,真替你爸妈丢人!
    答非所问,竟说一些,对方知道的老掉牙的事情。你Y 有病吧,你Y以为自己是陈冠希?张柏芝?还是杨幂薛凯琪啊。
    你这样狗嘴里吐不出象牙来你妈知道吗?
    你脑子豆腐渣做的吗?你爸妈知道吗?你是只狗,结果你吐出了象牙,你是狗跟大象杂交的是吧。
    那你就是连猪狗不如了,我哪里招你惹你了。
    就算我没有解答楼主的问题,你也用不着到处乱咬人吧,况且这里本来就是技术交流区,大家各抒己见而已。
    真不知道你爸妈怎么教育的你,真替你爸妈丢人!
    你大爷的,你个杂交货还知道有爸妈,你老师没教你懂礼貌啊,你的芭比没教你责任心啊,你妈比没教你出来乱咬要打疫苗啊,你可以乱叫,但不能乱咬啊,这他妈的传染。回家好好看看传统美德书,你就是混账知道不,见了张柏芝就叫妈,见了程冠希就叫爸,以为自己是谢霆锋啊,一个铁了心要当婊子的荡妇不要出来卖你的风骚,学学人家潘金莲,回去好好做掉你的大郎,勾搭你的大官人。给我滚蛋
    不可理喻,除了吠就是吠。在csdn,iteye等看你的回帖就没有几个正经的。
      

  11.   


    答非所问,竟说一些,对方知道的老掉牙的事情。你Y 有病吧,你Y以为自己是陈冠希?张柏芝?还是杨幂薛凯琪啊。
    你这样狗嘴里吐不出象牙来你妈知道吗?
    你脑子豆腐渣做的吗?你爸妈知道吗?你是只狗,结果你吐出了象牙,你是狗跟大象杂交的是吧。
    那你就是连猪狗不如了,我哪里招你惹你了。
    就算我没有解答楼主的问题,你也用不着到处乱咬人吧,况且这里本来就是技术交流区,大家各抒己见而已。
    真不知道你爸妈怎么教育的你,真替你爸妈丢人!
    答非所问,竟说一些,对方知道的老掉牙的事情。你Y 有病吧,你Y以为自己是陈冠希?张柏芝?还是杨幂薛凯琪啊。
    你这样狗嘴里吐不出象牙来你妈知道吗?
    你脑子豆腐渣做的吗?你爸妈知道吗?你是只狗,结果你吐出了象牙,你是狗跟大象杂交的是吧。
    那你就是连猪狗不如了,我哪里招你惹你了。
    就算我没有解答楼主的问题,你也用不着到处乱咬人吧,况且这里本来就是技术交流区,大家各抒己见而已。
    真不知道你爸妈怎么教育的你,真替你爸妈丢人!
    答非所问,竟说一些,对方知道的老掉牙的事情。你Y 有病吧,你Y以为自己是陈冠希?张柏芝?还是杨幂薛凯琪啊。
    你这样狗嘴里吐不出象牙来你妈知道吗?
    你脑子豆腐渣做的吗?你爸妈知道吗?你是只狗,结果你吐出了象牙,你是狗跟大象杂交的是吧。
    那你就是连猪狗不如了,我哪里招你惹你了。
    就算我没有解答楼主的问题,你也用不着到处乱咬人吧,况且这里本来就是技术交流区,大家各抒己见而已。
    真不知道你爸妈怎么教育的你,真替你爸妈丢人!
    你大爷的,你个杂交货还知道有爸妈,你老师没教你懂礼貌啊,你的芭比没教你责任心啊,你妈比没教你出来乱咬要打疫苗啊,你可以乱叫,但不能乱咬啊,这他妈的传染。回家好好看看传统美德书,你就是混账知道不,见了张柏芝就叫妈,见了程冠希就叫爸,以为自己是谢霆锋啊,一个铁了心要当婊子的荡妇不要出来卖你的风骚,学学人家潘金莲,回去好好做掉你的大郎,勾搭你的大官人。给我滚蛋
    不可理喻,除了吠就是吠。在csdn,iteye等看你的回帖就没有几个正经的。
    你Y有病是吧,非跟我乱叫是吧,我是没给你狗粮饿着你了还是,让拆迁办端了你的狗窝,让你无家可归了?
      

  12.   

    给int赋值,你看下汇编,好像有三行来的,,如果执行了二行就到另一个线程了,你说是原子吗
      

  13.   


    Google java 原子操作 基本类型 赋值
    https://www.google.com/search?num=20&newwindow=1&q=java+%E5%8E%9F%E5%AD%90%E6%93%8D%E4%BD%9C+%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B+%E8%B5%8B%E5%80%BC+&oq=java+%E5%8E%9F%E5%AD%90%E6%93%8D%E4%BD%9C+%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B+%E8%B5%8B%E5%80%BC
    http://blog.csdn.net/yuanwofei/article/details/12843591
    看汇编最真实。目前还没有哪一个cpu可以一条原子指令对一个4字节的位置进行赋值。而且我不任务java的编译器会把对int的赋值代码编译成头尾附加临界区的同步。
      

  14.   


    答非所问,竟说一些,对方知道的老掉牙的事情。你Y 有病吧,你Y以为自己是陈冠希?张柏芝?还是杨幂薛凯琪啊。
    你这样狗嘴里吐不出象牙来你妈知道吗?
    你脑子豆腐渣做的吗?你爸妈知道吗?你是只狗,结果你吐出了象牙,你是狗跟大象杂交的是吧。
    那你就是连猪狗不如了,我哪里招你惹你了。
    就算我没有解答楼主的问题,你也用不着到处乱咬人吧,况且这里本来就是技术交流区,大家各抒己见而已。
    真不知道你爸妈怎么教育的你,真替你爸妈丢人!
    答非所问,竟说一些,对方知道的老掉牙的事情。你Y 有病吧,你Y以为自己是陈冠希?张柏芝?还是杨幂薛凯琪啊。
    你这样狗嘴里吐不出象牙来你妈知道吗?
    你脑子豆腐渣做的吗?你爸妈知道吗?你是只狗,结果你吐出了象牙,你是狗跟大象杂交的是吧。
    那你就是连猪狗不如了,我哪里招你惹你了。
    就算我没有解答楼主的问题,你也用不着到处乱咬人吧,况且这里本来就是技术交流区,大家各抒己见而已。
    真不知道你爸妈怎么教育的你,真替你爸妈丢人!
    答非所问,竟说一些,对方知道的老掉牙的事情。你Y 有病吧,你Y以为自己是陈冠希?张柏芝?还是杨幂薛凯琪啊。
    你这样狗嘴里吐不出象牙来你妈知道吗?
    你脑子豆腐渣做的吗?你爸妈知道吗?你是只狗,结果你吐出了象牙,你是狗跟大象杂交的是吧。
    那你就是连猪狗不如了,我哪里招你惹你了。
    就算我没有解答楼主的问题,你也用不着到处乱咬人吧,况且这里本来就是技术交流区,大家各抒己见而已。
    真不知道你爸妈怎么教育的你,真替你爸妈丢人!
    你大爷的,你个杂交货还知道有爸妈,你老师没教你懂礼貌啊,你的芭比没教你责任心啊,你妈比没教你出来乱咬要打疫苗啊,你可以乱叫,但不能乱咬啊,这他妈的传染。回家好好看看传统美德书,你就是混账知道不,见了张柏芝就叫妈,见了程冠希就叫爸,以为自己是谢霆锋啊,一个铁了心要当婊子的荡妇不要出来卖你的风骚,学学人家潘金莲,回去好好做掉你的大郎,勾搭你的大官人。给我滚蛋
    不可理喻,除了吠就是吠。在csdn,iteye等看你的回帖就没有几个正经的。
    你Y有病是吧,非跟我乱叫是吧,我是没给你狗粮饿着你了还是,让拆迁办端了你的狗窝,让你无家可归了?
    你看看他的历史评论就知道他除了喷粪,还真的不干别得啥。
      

  15.   


    这个我也看到了,但是说AtomicInteger这个类,既然是原子操作的类,那么,为什么set方法没有同步,我也写了个测试,发现int赋值确实不是原子操作,我就更加不明白为什么Atomic的set方法不同步了。这个是代码,这样测试,发现确实是有问题的,总会走到System.err这里。public class Test {
    public static void main(String[] args) throws Exception {
    Run r = new Run();
    for (int i = 0; i < 10; i++)
    new Thread(r).start();
    }
    }class Run implements Runnable { static final int MIN = 0; static final int MAX = 2000000000; // 这里加不加volatile都是一样的结果。
    volatile int num = MIN; @Override
    public void run() {
    // 变量num就始终就两个取值,MIN和MAX,在这两个值之间来回赋值。
    // 如果发现num即不是MIN、也不是MAX,
    // 就会走到System.err输出这行代码,
    // 那么就说明有某个线程读取到了一个错误的值。
    for (int i = 0; i < 999999; i++) {
    if (num != MIN && num != MAX) {
    System.err.println("!!! ");
    return;
    }
    num = MAX;
    num = MIN; }
    }
    }
    改成这样,加上同步,就没问题了,不会走到System.err这里。public class Test {
    public static void main(String[] args) throws Exception {
    Run r = new Run();
    for (int i = 0; i < 10; i++)
    new Thread(r).start();
    }
    }class Run implements Runnable { static final int MIN = 0; static final int MAX = 2000000000; // 这里加不加volatile都是一样的结果。
    volatile int num = MIN; @Override
    public void run() {
    // 变量num就始终就两个取值,MIN和MAX,在这两个值之间来回赋值。
    // 如果发现num即不是MIN、也不是MAX,
    // 就会走到System.err输出这行代码,
    // 那么就说明有某个线程读取到了一个错误的值。
    for (int i = 0; i < 999999; i++) {
    synchronized (this) {
    if (num != MIN && num != MAX) {
    System.err.println("!!! ");
    return;
    }
    num = MAX;
    num = MIN;
    }
    }
    }
    }
    你的这段代码是有问题的:
    // 变量num就始终就两个取值,MIN和MAX,在这两个值之间来回赋值。
    // 如果发现num即不是MIN、也不是MAX,
    // 就会走到System.err输出这行代码,
    // 那么就说明有某个线程读取到了一个错误的值。
    for (int i = 0; i < 999999; i++) {
    if (num != MIN && num != MAX) {int的原子性可以保证 num变量要么是MIN ,要么是MAX,不可能出现其他值,但是现在问题出来你的测试代码上:
    if (num != MIN && num != MAX) 
    这个判断是不能保证的,当 执行到 num != MIN 时, num的值是MAX,但是当执行到 num != MAX 时,num的值可能已经变成MIN了,所以会导致你这段代码会走到 System.err。 而 加上同步块就不会出现这个问题了。