Java concurrency之AtomicLong原子类_动力节点Java学院整理
程序员文章站
2023-12-21 10:48:58
atomiclong介绍和函数列表
atomiclong是作用是对长整形进行原子操作。
在32位操作系统中,64位的long 和 double 变量由于会被jvm当作两...
atomiclong介绍和函数列表
atomiclong是作用是对长整形进行原子操作。
在32位操作系统中,64位的long 和 double 变量由于会被jvm当作两个分离的32位来进行操作,所以不具有原子性。而使用atomiclong能让long的操作保持原子型。
atomiclong函数列表
// 构造函数 atomiclong() // 创建值为initialvalue的atomiclong对象 atomiclong(long initialvalue) // 以原子方式设置当前值为newvalue。 final void set(long newvalue) // 获取当前值 final long get() // 以原子方式将当前值减 1,并返回减1后的值。等价于“--num” final long decrementandget() // 以原子方式将当前值减 1,并返回减1前的值。等价于“num--” final long getanddecrement() // 以原子方式将当前值加 1,并返回加1后的值。等价于“++num” final long incrementandget() // 以原子方式将当前值加 1,并返回加1前的值。等价于“num++” final long getandincrement() // 以原子方式将delta与当前值相加,并返回相加后的值。 final long addandget(long delta) // 以原子方式将delta添加到当前值,并返回相加前的值。 final long getandadd(long delta) // 如果当前值 == expect,则以原子方式将该值设置为update。成功返回true,否则返回false,并且不修改原值。 final boolean compareandset(long expect, long update) // 以原子方式设置当前值为newvalue,并返回旧值。 final long getandset(long newvalue) // 返回当前值对应的int值 int intvalue() // 获取当前值对应的long值 long longvalue() // 以 float 形式返回当前值 float floatvalue() // 以 double 形式返回当前值 double doublevalue() // 最后设置为给定值。延时设置变量值,这个等价于set()方法,但是由于字段是volatile类型的,因此次字段的修改会比普通字段(非volatile字段)有稍微的性能延时(尽管可以忽略),所以如果不是想立即读取设置的新值,允许在“后台”修改值,那么此方法就很有用。如果还是难以理解,这里就类似于启动一个后台线程如执行修改新值的任务,原线程就不等待修改结果立即返回(这种解释其实是不正确的,但是可以这么理解)。 final void lazyset(long newvalue) // 如果当前值 == 预期值,则以原子方式将该设置为给定的更新值。jsr规范中说:以原子方式读取和有条件地写入变量但不 创建任何 happen-before 排序,因此不提供与除 weakcompareandset 目标外任何变量以前或后续读取或写入操作有关的任何保证。大意就是说调用weakcompareandset时并不能保证不存在happen-before的发生(也就是可能存在指令重排序导致此操作失败)。但是从java源码来看,其实此方法并没有实现jsr规范的要求,最后效果和compareandset是等效的,都调用了unsafe.compareandswapint()完成操作。 final boolean weakcompareandset(long expect, long update)
atomiclong源码分析(基于jdk1.7.0_40)
atomiclong的完整源码
/* * oracle proprietary/confidential. use is subject to license terms. * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * written by doug lea with assistance from members of jcp jsr- * expert group and released to the public domain, as explained at * http://creativecommons.org/publicdomain/zero/./ */ package java.util.concurrent.atomic; import sun.misc.unsafe; /** * a {@code long} value that may be updated atomically. see the * {@link java.util.concurrent.atomic} package specification for * description of the properties of atomic variables. an * {@code atomiclong} is used in applications such as atomically * incremented sequence numbers, and cannot be used as a replacement * for a {@link java.lang.long}. however, this class does extend * {@code number} to allow uniform access by tools and utilities that * deal with numerically-based classes. * * @since . * @author doug lea */ public class atomiclong extends number implements java.io.serializable { private static final long serialversionuid = l; // setup to use unsafe.compareandswaplong for updates private static final unsafe unsafe = unsafe.getunsafe(); private static final long valueoffset; /** * records whether the underlying jvm supports lockless * compareandswap for longs. while the unsafe.compareandswaplong * method works in either case, some constructions should be * handled at java level to avoid locking user-visible locks. */ static final boolean vm_supports_long_cas = vmsupportscs(); /** * returns whether underlying jvm supports lockless compareandset * for longs. called only once and cached in vm_supports_long_cas. */ private static native boolean vmsupportscs(); static { try { valueoffset = unsafe.objectfieldoffset (atomiclong.class.getdeclaredfield("value")); } catch (exception ex) { throw new error(ex); } } private volatile long value; /** * creates a new atomiclong with the given initial value. * * @param initialvalue the initial value */ public atomiclong(long initialvalue) { value = initialvalue; } /** * creates a new atomiclong with initial value {@code }. */ public atomiclong() { } /** * gets the current value. * * @return the current value */ public final long get() { return value; } /** * sets to the given value. * * @param newvalue the new value */ public final void set(long newvalue) { value = newvalue; } /** * eventually sets to the given value. * * @param newvalue the new value * @since 1.6 */ public final void lazyset(long newvalue) { unsafe.putorderedlong(this, valueoffset, newvalue); } /** * atomically sets to the given value and returns the old value. * * @param newvalue the new value * @return the previous value */ public final long getandset(long newvalue) { while (true) { long current = get(); if (compareandset(current, newvalue)) return current; } } /** * atomically sets the value to the given updated value * if the current value {@code ==} the expected value. * * @param expect the expected value * @param update the new value * @return true if successful. false return indicates that * the actual value was not equal to the expected value. */ public final boolean compareandset(long expect, long update) { return unsafe.compareandswaplong(this, valueoffset, expect, update); } /** * atomically sets the value to the given updated value * if the current value {@code ==} the expected value. * * <p>may <a href="package-summary.html#spurious" rel="external nofollow" >fail spuriously</a> * and does not provide ordering guarantees, so is only rarely an * appropriate alternative to {@code compareandset}. * * @param expect the expected value * @param update the new value * @return true if successful. */ public final boolean weakcompareandset(long expect, long update) { return unsafe.compareandswaplong(this, valueoffset, expect, update); } /** * atomically increments by one the current value. * * @return the previous value */ public final long getandincrement() { while (true) { long current = get(); long next = current + 1; if (compareandset(current, next)) return current; } } /** * atomically decrements by one the current value. * * @return the previous value */ public final long getanddecrement() { while (true) { long current = get(); long next = current - 1; if (compareandset(current, next)) return current; } } /** * atomically adds the given value to the current value. * * @param delta the value to add * @return the previous value */ public final long getandadd(long delta) { while (true) { long current = get(); long next = current + delta; if (compareandset(current, next)) return current; } } /** * atomically increments by one the current value. * * @return the updated value */ public final long incrementandget() { for (;;) { long current = get(); long next = current + 1; if (compareandset(current, next)) return next; } } /** * atomically decrements by one the current value. * * @return the updated value */ public final long decrementandget() { for (;;) { long current = get(); long next = current - 1; if (compareandset(current, next)) return next; } } /** * atomically adds the given value to the current value. * * @param delta the value to add * @return the updated value */ public final long addandget(long delta) { for (;;) { long current = get(); long next = current + delta; if (compareandset(current, next)) return next; } } /** * returns the string representation of the current value. * @return the string representation of the current value. */ public string tostring() { return long.tostring(get()); } public int intvalue() { return (int)get(); } public long longvalue() { return get(); } public float floatvalue() { return (float)get(); } public double doublevalue() { return (double)get(); } }
atomiclong的代码很简单,下面仅以incrementandget()为例,对atomiclong的原理进行说明。
incrementandget()源码如下:
public final long incrementandget() { for (;;) { // 获取atomiclong当前对应的long值 long current = get(); // 将current加1 long next = current + 1; // 通过cas函数,更新current的值 if (compareandset(current, next)) return next; } }
说明:
(01) incrementandget()首先会根据get()获取atomiclong对应的long值。该值是volatile类型的变量,get()的源码如下:
// value是atomiclong对应的long值 private volatile long value; // 返回atomiclong对应的long值 public final long get() { return value; }
(02) incrementandget()接着将current加1,然后通过cas函数,将新的值赋值给value。
compareandset()的源码如下:
public final boolean compareandset(long expect, long update) { return unsafe.compareandswaplong(this, valueoffset, expect, update); }
compareandset()的作用是更新atomiclong对应的long值。它会比较atomiclong的原始值是否与expect相等,若相等的话,则设置atomiclong的值为update。
atomiclong示例
// longtest.java的源码 import java.util.concurrent.atomic.atomiclong; public class longtest { public static void main(string[] args){ // 新建atomiclong对象 atomiclong matolong = new atomiclong(); matolong.set(0x0123456789abcdefl); system.out.printf("%20s : 0x%016x\n", "get()", matolong.get()); system.out.printf("%20s : 0x%016x\n", "intvalue()", matolong.intvalue()); system.out.printf("%20s : 0x%016x\n", "longvalue()", matolong.longvalue()); system.out.printf("%20s : %s\n", "doublevalue()", matolong.doublevalue()); system.out.printf("%20s : %s\n", "floatvalue()", matolong.floatvalue()); system.out.printf("%20s : 0x%016x\n", "getanddecrement()", matolong.getanddecrement()); system.out.printf("%20s : 0x%016x\n", "decrementandget()", matolong.decrementandget()); system.out.printf("%20s : 0x%016x\n", "getandincrement()", matolong.getandincrement()); system.out.printf("%20s : 0x%016x\n", "incrementandget()", matolong.incrementandget()); system.out.printf("%20s : 0x%016x\n", "addandget(0x10)", matolong.addandget(0x10)); system.out.printf("%20s : 0x%016x\n", "getandadd(0x10)", matolong.getandadd(0x10)); system.out.printf("\n%20s : 0x%016x\n", "get()", matolong.get()); system.out.printf("%20s : %s\n", "compareandset()", matolong.compareandset(0x12345679l, 0xfedcba9876543210l)); system.out.printf("%20s : 0x%016x\n", "get()", matolong.get()); } }
运行结果:
get() : 0x0123456789abcdef intvalue() : 0x0000000089abcdef longvalue() : 0x0123456789abcdef doublevalue() : 8.1985529216486896e16 floatvalue() : 8.1985531e16 getanddecrement() : 0x0123456789abcdef decrementandget() : 0x0123456789abcded getandincrement() : 0x0123456789abcded incrementandget() : 0x0123456789abcdef addandget(0x10) : 0x0123456789abcdff getandadd(0x10) : 0x0123456789abcdff get() : 0x0123456789abce0f compareandset() : false get() : 0x0123456789abce0f
以上所述是小编给大家介绍的java concurrency之atomiclong原子类,希望对大家有所帮助
推荐阅读
-
Java concurrency之AtomicLong原子类_动力节点Java学院整理
-
Java concurrency之AtomicReference原子类_动力节点Java学院整理
-
Java concurrency之互斥锁_动力节点Java学院整理
-
Java8新特性之JavaFX 8_动力节点Java学院整理
-
Java concurrency之锁_动力节点Java学院整理
-
Java8新特性之Base64详解_动力节点Java学院整理
-
Java8新特性之泛型的目标类型推断_动力节点Java学院整理
-
Java8新特性之StampedLock_动力节点Java学院整理
-
Java8新特性之lambda的作用_动力节点Java学院整理
-
Java数据库连接池之proxool_动力节点Java学院整理