原子操作类-总结

2019-07-17  本文已影响0人  王侦

1.官方描述

1.1 单个变量AtomicBoolean, AtomicInteger, AtomicLong和AtomicReference

A small toolkit of classes that support lock-free thread-safe 
programming on single variables. In essence, the classes in this 
package extend the notion of volatile values, fields, and array 
elements to those that also provide an atomic conditional update 
operation of the form:

  boolean compareAndSet(expectedValue, updateValue);

This method (which varies in argument types across different 
classes) atomically sets a variable to the updateValue if it 
currently holds the expectedValue, reporting true on success. The 
classes in this package also contain methods to get and 
unconditionally set values, as well as a weaker conditional atomic 
update operation weakCompareAndSet described below.

The specifications of these methods enable implementations to 
employ efficient machine-level atomic instructions that are 
available on contemporary processors. However on some 
platforms, support may entail some form of internal locking. Thus 
the methods are not strictly guaranteed to be non-blocking -- a 
thread may block transiently before performing the operation.

支持对单变量无锁线程安全编程。使用CAS拓展了volatile概念。

CAS一般采用高效机器级原子指令实现,但是在某些平台,可能需要内部锁来支持。因此,不严格保证方法是非阻塞的,线程可能在执行操作之前暂时阻塞。

Instances of classes AtomicBoolean, AtomicInteger, AtomicLong, 
and AtomicReference each provide access and updates to a 
single variable of the corresponding type. Each class also 
provides appropriate utility methods for that type. For example, 
classes AtomicLong and AtomicInteger provide atomic increment 
methods. One application is to generate sequence numbers, as 
in:

类AtomicBoolean, AtomicInteger, AtomicLong和AtomicReference的实例分别提供了对相应类型的单个变量的访问和更新,每个类还为该类型提供了适当的实用方法。例如,AtomicBoolean, AtomicInteger提供了原子增量方法。

 class Sequencer {
   private final AtomicLong sequenceNumber
     = new AtomicLong(0);
   public long next() {
     return sequenceNumber.getAndIncrement();
   }
 }
It is straightforward to define new utility functions that, like 
getAndIncrement, apply a function to a value atomically. For 
example, given some transformation

  long transform(long input)

定义新的实用程序函数很简单,像getAndIncrement,将函数原子地应用于值。

write your utility method as follows:

 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 memory effects for accesses and updates of atomics 
generally follow the rules for volatiles, as stated in The Java 
Language Specification (17.4 Memory Model):

* get has the memory effects of reading a volatile variable.
* set has the memory effects of writing (assigning) a volatile variable.
* lazySet has the memory effects of writing (assigning) a volatile 
  variable except that it permits reorderings with subsequent (but 
  not previous) memory actions that do not themselves impose 
  reordering constraints with ordinary non-volatile writes. Among 
  other usage contexts, lazySet may apply when nulling out, for the 
  sake of garbage collection, a reference that is never accessed 
  again.
* weakCompareAndSet atomically reads and conditionally writes 
  a variable but does not create any happens-before orderings, so 
  provides no guarantees with respect to previous or subsequent 
  reads and writes of any variables other than the target of the 
  weakCompareAndSet.
* compareAndSet and all other read-and-update operations such 
  as getAndIncrement have the memory effects of both reading and 
  writing volatile variables.

访问和更新原子类的内存效应遵循volatile的规则,如果Java语言规范中所述(17.4 Memory Model):

1.2 域AtomicReferenceFieldUpdater, AtomicIntegerFieldUpdater及AtomicLongFieldUpdater

In addition to classes representing single values, this package 
contains Updater classes that can be used to obtain 
compareAndSet operations on any selected volatile field of any 
selected class. AtomicReferenceFieldUpdater, 
AtomicIntegerFieldUpdater, and AtomicLongFieldUpdater are 
reflection-based utilities that provide access to the associated 
field types. These are mainly of use in atomic data structures in 
which several volatile fields of the same node (for example, the 
links of a tree node) are independently subject to atomic updates.
 These classes enable greater flexibility in how and when to use 
atomic updates, at the expense of more awkward reflection-
based setup, less convenient usage, and weaker guarantees.

可以在任何类的volatile域上执行CAS操作。AtomicReferenceFieldUpdater, AtomicIntegerFieldUpdater及AtomicLongFieldUpdater这三个类是基于反射的,可提供对相关字段的访问。通常用于原子数据结构,在同一结点中有几个volatile域,可以独立地进行原子更新。这些类在如何以及何时使用原子更新方面提供了更大的灵活性,代价是笨拙的基于反射的设置,不太方便的使用和较弱的保证。

1.3 数组AtomicIntegerArray, AtomicLongArray和AtomicReferenceArray

The AtomicIntegerArray, AtomicLongArray, and 
AtomicReferenceArray classes further extend atomic operation 
support to arrays of these types. These classes are also notable
 in providing volatile access semantics for their array elements, 
which is not supported for ordinary arrays.

1.4 weakCompareAndSet

The atomic classes also support method weakCompareAndSet, 
which has limited applicability. On some platforms, the weak 
version may be more efficient than compareAndSet in the normal 
case, but differs in that any given invocation of the 
weakCompareAndSet method may return false spuriously (that is, 
for no apparent reason). A false return means only that the 
operation may be retried if desired, relying on the guarantee that 
repeated invocation when the variable holds expectedValue and 
no other thread is also attempting to set the variable will 
eventually succeed. (Such spurious failures may for example be 
due to memory contention effects that are unrelated to whether 
the expected and current values are equal.) Additionally 
weakCompareAndSet does not provide ordering guarantees that 
are usually needed for synchronization control. However, the 
method may be useful for updating counters and statistics when 
such updates are unrelated to the other happens-before 
orderings of a program. When a thread sees an update to an 
atomic variable caused by a weakCompareAndSet, it does not 
necessarily see updates to any other variables that occurred 
before the weakCompareAndSet. This may be acceptable when, 
for example, updating performance statistics, but rarely 
otherwise.

weakCompareAndSet适用性有限。在某些平台上,弱版本可能比普通情况下的compareAndSet更高效,但不同之处在于,任何给定的weakCompareAndSet方法调用都可能虚假地返回false(没有明显的原因)。错误返回仅表示如果需要可以重试操作,依赖于如下保证:当变量保持expectedValue时没有其他线程尝试设置变量,重复调用最终会成功。(例如,这种虚假故障可能是由于与预期值和当前值相等无关的内存争用效应。)另外,weakCompareAndSet不提供同步控制通常需要的排序保证。然而,该方法对于更新计数器和统计数据可能是有用的,当这些更新与其他程序的happens-before顺序无关时。当线程看到由weakCompareAndSet引起的原子变量更新时,它不必一定得看到在weakCompareAndSet之前发生的任何其他变量的更新。这在某些情况下是可接受的,例如更新性能统计信息,在其他情况下很少。

1.5 关联标记AtomicMarkableReference和AtomicStampedReference

The AtomicMarkableReference class associates a single boolean 
with a reference. For example, this bit might be used inside a 
data structure to mean that the object being referenced has 
logically been deleted. The AtomicStampedReference class 
associates an integer value with a reference. This may be used 
for example, to represent version numbers corresponding to 
series of updates.

AtomicMarkableReference类将单个布尔值与引用相关联。该位可在数据结构中表示被引用的对象在逻辑上是否已被删除。 AtomicStampedReference类将整数值与引用相关联。可用于表示与一系列更新相对应的版本号。

1.6 注意事项

Atomic classes are designed primarily as building blocks for 
implementing non-blocking data structures and related 
infrastructure classes. The compareAndSet method is not a 
general replacement for locking. It applies only when critical 
updates for an object are confined to a single variable.

Atomic classes are not general purpose replacements for 
java.lang.Integer and related classes. They do not define 
methods such as equals, hashCode and compareTo. (Because 
atomic variables are expected to be mutated, they are poor 
choices for hash table keys.) Additionally, classes are provided 
only for those types that are commonly useful in intended 
applications. For example, there is no atomic class for 
representing byte. In those infrequent cases where you would like 
to do so, you can use an AtomicInteger to hold byte values, and 
cast appropriately. You can also hold floats using 
Float.floatToRawIntBits(float) and Float.intBitsToFloat(int) 
conversions, and doubles using 
Double.doubleToRawLongBits(double) and 
Double.longBitsToDouble(long) conversions.

2.消耗对比

对于CPU的消耗来说,其从小到大依次为:

3.AtomicReferenceFieldUpdater, AtomicIntegerFieldUpdater及AtomicLongFieldUpdater弱保证性

Note that the guarantees of the compareAndSet method in this 
class are weaker than in other atomic classes. Because this class 
cannot ensure that all uses of the field are appropriate for 
purposes of atomic access, it can guarantee atomicity only with 
respect to other invocations of compareAndSet and set on the 
same updater.

请注意,此类中compareAndSet方法的保证比其他原子类弱。 因为此类无法确保该字段的所有使用都适用于原子访问的目的,只能保证相同updater上执行CAS和set操作的原子性,因此它的原子性是弱于AtomicLong的。

AtomicLong是对long型属性加了一层原子引用,任何想要修改该long值的操作都需要先获得该原子引用,而updater不会为属性增加原子引用,它是通过反射技术,通过外部操作去修改long型属性值,因此它的原子保证也是通过外部限制的,因此只能保证同一updater进行CAS和set的原子性。

上一篇 下一篇

猜你喜欢

热点阅读