Implementation
compareAndSet and all other read-and-update operations such as getAndIncrement have the memory effects of both reading and writing volatile variables.
Are implemented by calling CAS operations provided by java.misc.Unsafe
Unsafe treats both Array & Object in the same way. They both have an Object reference + offSet that determines the position (address) (index in array) of the value to be updated.
The method used ( compareAndSwapInt() / compareAndSwapObject() )determines the type of value to expect at the calculated location.
unsafe.compareAndSwapObject(obj, offset, expect, update);
obj - The Instance/Object that contains the variable to be updated
offset - the address offset form start of the Instance/Object that contains the variable
expected - the expected value contained at the base+offset address
update - the new value to be written at the base+offset address
AtomicInteger
volatile int value - The value (holder) is defined as volatile
final long valueOffset = offset of the 'value' field in the AtomicInteger from start of the AtomicInteger instance.
get() & set() are simple read of volatile.
so are intValue(), longValue(), floatValue(), doubleValue().
getAndSet() - invokes the CAS operation - Unsafe.compareAndSwapInt(this, valueOffset, var1, var2);
so do getAndIncrement(), getAndDecrement(), decrementAndGet(), getAndAdd(int delta), addAndGet(int delta), incrementAndGet()
lazySet() - Eventually sets to the given value. Calls Unsafe.putOrderedInt()
The volatile field gives us the Visibility Guarantee.
The CAS operations give us the Atomicity (non corrupted values)
AtomicIntegerArray
There is no volatile field in the class but the operations invoked are volatile. They have volatile semantics.
final int[] is used - to provide visibility. // Visibility guaranteed by final field guarantees
During array initialisation one entry is added using Unsafe.putIntVolatile() - to make the array volatile ??.. No Think its for visibility. All previous element writes get published.
base * scale are calculated during loading (static final variables)
base = start location of first element in the array
scale = memory taken by one element (4 Bytes for int 8 Bytes for long)
ith element address is = base + (scale * i)
lazySet() - Eventually sets the element at position {@code i} to the given value.
All Modification operations invoke CAS operation
abstract class AtomicIntegerFieldUpdater<T>
A reflection-based utility that enables atomic updates to designated volatile int fields of designated classes.
Similar to Collections.synchronise();
Decorator pattern ??
AtomicReference
Similar to AtomicInteger
T value - field is volatile and maintains reference to the Object.
Calls Unsafe.CASOpsObject instead of Unsafe.CASOpsInt
AtomicReferenceArray
final Object[]
// Visibility guaranteed by final field guarantees
Semaphores
A semaphore is a counter of permits and acquire is like decrement which waits rather than go below zero. It has no upper limit.
A Semaphore is not limited to the number of permits it was created with.
Implementation
to be added..
Semaphores should not be used in the place of synchronized because semaphores does not hold exclusive mutual lock even if it is initialized to one, like synchronized on some object.
It is true that the semaphore initialized to one, allows only one thread at a time to access the object, which holds the permit. But the thread which holds the permit does not own it, any other thread could release that permit and acquire the permit.
So, two threads could get access to the same object at the same time, and if both threads manipulates that object, there will be multi-threading issues like lost update, stale read etc.
In an example of having 2 threads, one increasing and one decreasing the same variable. mutual exclusion is sufficient and volatile declaration is not needed. here I assume mutual exclusion is achieved via synchronized and not by semaphores.
volatile is less strict than synchronized, you may want to use volatile when the operations performed are atomic (read or write). volatile should not be used when the performing read-update-write operation.
No comments:
Post a Comment