版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_37933685/article/details/80888972
环境:jdkapi1.8 Package java.util.concurrent.atomic Description 一个小型工具包,支持单个变量上的无锁线程安全编程。 从本质上说,在该包中的类延伸的概念volatile值,字段和数组元素的那些也提供以下形式的原子条件更新操作: boolean compareAndSet(expectedValue, updateValue); 这种方法(在不同类中的参数类型不同)原子地将变量设置为updateValue如果它当前持有expectedValue ,报告true成功。 该包中的类还包含获取和无条件设置值的方法,以及下面描述的较弱条件原子更新操作weakCompareAndSet 。
这些方法的规范使实现能够采用当代处理器上可用的高效机器级原子指令。 然而,在某些平台上,支持可能需要某种形式的内部锁定。 因此,这些方法不是严格保证是非阻塞的 - 线程可能在执行操作之前暂时阻塞。
类的实例AtomicBoolean , AtomicInteger , AtomicLong和AtomicReference各自提供访问和更新相应的类型的单个变量。 每个类还提供了适用于该类型的实用方法。 例如,类AtomicLong和AtomicInteger提供原子增量方法。 一个应用是生成序列号,如:
class Sequencer { private final AtomicLong sequenceNumber = new AtomicLong(0); public long next() { return sequenceNumber.getAndIncrement(); } } 定义新的效用函数是很getAndIncrement ,像getAndIncrement一样,将函数应用于一个值。 例如,给定一些转换
long transform(long input) 写你的实用方法如下: long getAndTransform(AtomicLong var) { long prev, next; do { prev = var.get(); next = transform(prev); } while (!var.compareAndSet(prev, next)); return prev; // return next; for transformAndGet } 访问和更新原子的记忆效应通常遵循挥发物的规则,如The Java Language Specification (17.4 Memory Model)所述 :
get具有读取volatile变量的记忆效应。 set具有写(分配) volatile变量的记忆效应。 lazySet具有写入(分配) volatile变量的记忆效应,除了它允许重新排序与后续(但不是先前)存储器动作,它们本身不会对普通非volatile写入施加重新排序volatile 。 在其他使用上下文中, lazySet可以在为了垃圾收集而被归零时应用于再次不会被访问的引用。 weakCompareAndSet原子方式读取和有条件地写入一个变量,但不会产生任何事先的排序,因此对于weakCompareAndSet以外的任何变量的前一次或后续读取和写入都不提供任何weakCompareAndSet 。 compareAndSet和所有其他读取和更新操作(如getAndIncrement具有读写volatile变量的记忆效应。 除了表示单个值的类之外,此程序包还包含Updater类,可用于在任何所选volatile任何选定的volatile字段上获取compareAndSet操作。 AtomicReferenceFieldUpdater , AtomicIntegerFieldUpdater和AtomicLongFieldUpdater是基于反射的实用程序,提供对相关联的字段类型。 这些主要用于原子数据结构中,其中相同节点(例如,树节点的链接)的多个volatile字段独立地受到原子更新的影响。 这些类可以在如何和何时使用原子更新方面提供更大的灵活性,牺牲更加尴尬的基于反射的设置,不太方便的使用和更弱的保证。
的AtomicIntegerArray , AtomicLongArray和AtomicReferenceArray类进一步扩展到这些类型的数组原子操作的支持。 这些类别对于为其数组元素提供volatile访问语义也是值得注意的,这对普通数组是不支持的。
原子类也支持方法weakCompareAndSet ,其适用性有限。 在某些平台上,所述弱版本可以比更有效compareAndSet在正常情况下,但不同之处在于的任何给定调用weakCompareAndSet方法可返回false 不合逻辑地 (即,没有明显的原因)。 一个false返回只意味着如果需要,可以重试该操作,依赖于当该变量保持expectedValue时重复调用的expectedValue ,并且没有其他线程也尝试设置该变量将最终成功。 (这样的虚假故障可能是由于与预期值和当前值是否相等无关的内存争用效应)。另外, weakCompareAndSet不提供同步控制通常需要的排序保证。 然而,当这样的更新与程序的排序之前的另一个发生无关时,该方法可用于更新计数器和统计信息。 当线程看到由weakCompareAndSet引起的原子变量的更新时,它不一定会看到在weakCompareAndSet之前发生的任何其他变量的weakCompareAndSet 。 例如,如果更新性能统计数据,但很少有其他的情况,这可能是可以接受的。
AtomicMarkableReference类将一个布尔值与引用相关联。 例如,该位可能在数据结构中使用,意味着被引用的对象在逻辑上被删除。 AtomicStampedReference类将整数值与引用相关联。 这可以用于例如表示对应于一系列更新的版本号。
原子类主要设计为实现非阻塞数据结构和相关基础设施类的构建块。 compareAndSet方法不是锁定的一般compareAndSet方法。 仅当对象的关键更新仅限于单个变量时,才适用。
原子类不是通用替代java.lang.Integer和相关类。 他们没有定义的方法,如equals , hashCode和compareTo 。 (因为原子变量预计会被突变,所以它们是散列表键的不好选择。)此外,类仅提供给预期应用程序通常有用的类型。 例如,对于表示无原子类byte 。 在那些您不希望这样做的情况下,您可以使用AtomicInteger来保存byte值,并适当地投射。 您也可以使用Float.floatToRawIntBits(float)和Float.intBitsToFloat(int)转换来持有浮点数,并使用Double.doubleToRawLongBits(double)和Double.longBitsToDouble(long)转换双倍。
从以下版本开始: 1.5