原文:http://www.quora.com/Java-programming-language/How-does-AtomicLong-lazySet-work

Jackson Davis说:为一个 AtomicLong 对象设置一个值,JVM 会确保其他线程读取到最新值,原子类和 voliatile 变量也是一样的,这是由依赖于硬件的系统指令(如 x86 的 xchg )实现的。lazySet 却是无法保证这一点的方法,所以其他线程在之后的一小段时间里还是可以读到旧的值。

这有什么好处呢?

性能:在多核处理器下,内存以及 CPU 缓存的读和写常常是顺序执行的,所以在多个 CPU 缓存之间同步一个内存值的代价是很昂贵的。

如何实现呢?

大多数的原子类,比如 AtomicLong 本质上都是一个 Unsafe 和一个 volatile Long 变量的包装类。值得注意的是 AtomicLong.lazySet 方法实际是调用了本地方法 Unsafe.putOrderedLong,本地方法 Unsafe.putOrderedLong 的实现可以参考 http://hg.openjdk.java.net/jdk7/…。

public final void lazySet(int newValue) {    unsafe.putOrderedInt(this, valueOffset, newValue);}  

从 Unsafe 的代码中可以发现 Unsafe_setOrderedLong 是一个本地方法(c++ 实现),它仅调用了 SET_FIELD_VOLATILE,这很是奇怪,我们期望共享的 Unsafe_setLongVolatile 拥有不同的语义。

PS:在非增强版本中,setOrdered 仅仅是调用了 setVolatile 方法,很是让人失望。深入查看你会发现其实它们是相同的,SET_FIELD_VOLATILE 是一个 OrderAccess:release_store_fence 的包装。可以在 Linux x86的代码 http://hg.openjdk.java.net/jdk7/… 中找到此方法的实现,在 64bit x86 系统中采用 xchgq 来代码,64位版本指令的问题我上面有提到过。

ps:从理论上讲 lazySet 能比一个标准的 volatile 变量的写性能更好。但是我在 openJdk 里没有找到相关代码。

Felix Sulima说:

sun.misc.unsafe 很多方法被 JVM 增强了,JIT(just in time 运行时编译执行的技术)直接解释而忽略原始的实现。可以在这里找到这个例子:src/share/vm/classfile/vmSymbols.hpp@3facbb14e873列表中的 native 方法仅仅是非 JIT 环境下的一个备份的内部方法。例如,如果它没有被调用(我也不知道是什么原因),因此这些方法缺乏一些必要的优化。从 Talk from JAX London 的幻灯片 11-12 可以看到 AtomicLong.lazySet(…) 在 x86 系统上会被编译成 "mov" 指令。这里是 Google Group 里关于如何获得 JIT 装配的一个描述。

看的一脸懵逼。

AtomicLong.lazySet 是如何工作的?的更多相关文章

  1. JDK中的Atomic包中的类及使用

    引言 Java从JDK1.5开始提供了java.util.concurrent.atomic包,方便程序员在多线程环境下,无锁的进行原子操作.原子变量的底层使用了处理器提供的原子指令,但是不同的CPU ...

  2. JAVA多线程提高五:原子性操作类的应用

    当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量i=1,A线程更新i+1,B线程也更新i+1,经过两个线程操作之后可能i不等于3,而是等于2.因为A和B线程在更新变量i ...

  3. Java中的原子操作类

    转载: <ava并发编程的艺术>第7章 当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量i=1,A线程更新i+1,B线程也更新i+1,经过两个线程操作之后可 ...

  4. JAVA多线程学习九-原子性操作类的应用

    当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量i=1,A线程更新i+1,B线程也更新i+1,经过两个线程操作之后可能i不等于3,而是等于2.因为A和B线程在更新变量i ...

  5. 二、多线程之Atomic包

    一.简介 1.原子操作 我们在使用变量的时候,经常会出现资源竞争的情况,为了保证变量安全,我们就会对对应的方法添加"synchronized"同步锁来达到目的,以保证线程安全. 而 ...

  6. 详解volatile关键字和原子引用

    本篇看一下Volatile关键字和原子引用. 上图就是JUC包结构,总共分成三块 (1)java.util.concurrent:并发包基础类,包括阻塞队列,线程池相关类,线程安全Map等. (2)j ...

  7. 从零开始实现lmax-Disruptor队列(一)RingBuffer与单生产者、单消费者工作原理解析

    1.lmax-Disruptor队列介绍 disruptor是英国著名的金融交易所lmax旗下技术团队开发的一款java实现的高性能内存队列框架 其发明disruptor的主要目的是为了改进传统的内存 ...

  8. Java多线程系列--“JUC原子类”02之 AtomicLong原子类

    概要 AtomicInteger, AtomicLong和AtomicBoolean这3个基本类型的原子类的原理和用法相似.本章以AtomicLong对基本类型的原子类进行介绍.内容包括:Atomic ...

  9. 多线程爬坑之路-J.U.C.atomic包下的AtomicInteger,AtomicLong等类的源码解析

    Atomic原子类:为基本类型的封装类Boolean,Integer,Long,对象引用等提供原子操作. 一.Atomic包下的所有类如下表: 类摘要 AtomicBoolean 可以用原子方式更新的 ...

随机推荐

  1. win10搭建tensorflow-gpu环境

    昨天辛苦的配了GPU环境,记录一下防止以后还需要用到. 我配GPU的目的是用tensorflow的gpu来加速 不用ubuntu是因为一来不习惯,二来我不会配ubuntu的扩展显示器,就更不习惯了,习 ...

  2. 算法进阶面试题03——构造数组的MaxTree、最大子矩阵的大小、2017京东环形烽火台问题、介绍Morris遍历并实现前序/中序/后序

    接着第二课的内容和带点第三课的内容. (回顾)准备一个栈,从大到小排列,具体参考上一课.... 构造数组的MaxTree [题目] 定义二叉树如下: public class Node{ public ...

  3. XHR对象

    一.XMLHttpRequest对象 var xhr = new XMLHttpRequest(), i = 0; for(var key in xhr){ if(xhr.hasOwnProperty ...

  4. Gephi可视化(二)

    继在园子里写的<Gephi可视化(一)——使用Gephi Toolkit创建Gephi应用>介绍了如何使用Gephi Toolkit工具集进行可视化编程后,本篇对Gephi Toolkit ...

  5. adb monkey测试 命令

    adb shell monkey -p cn.com.linktrust.als.ipad 3500 LOWED_PACKAGE [-p ALLOWED_PACKAGE] ...] [-c MAIN_ ...

  6. Redis的使用(待更新)

    import redis #redis的使用 """ { "k1":"v1", 'names': ['把几个','鲁宁','把几个 ...

  7. stdlib库中qsort函数的使用

    qsort :功 能: 使用快速排序例程进行排序  用 法: void qsort(void *base, int nelem, int width, int (*fcmp)(const void * ...

  8. API使用

    至于什么是API我想不用累述了,百科上面有,其实就是别人写好了一大堆功能性的代码,然后你可以拿来用.一般的二次开发都是使用api来开发,包括现在的高级程序设计,很少自己写基本代码了,像.netFram ...

  9. js获取本机id

    var hostname = location.hostname; window.location.href="http://"+hostname+":8080/zhib ...

  10. ftp命令详解补充

     下面我来详细地介绍一个登陆FTP的命令和步骤吧: FTP命令是Internet用户使用最频繁的命令之一,不论是在DOS还是UNIX操作系统下使用FTP,都会遇到大量的FTP内部命令.熟悉并灵活应用F ...