Java AtomicMarkableReference Example
In this example we shall make use of AtomicMarkableReference
class of Java. It is another class under the java.util.concurrent.atomic
package, which provides lock-free and thread-safe programming solutions. In a recent example, we have seen how the AtomicReference
class can be utilized to provide reference objects that may be atomically updated. Atomic actions are actions performed in an object only by one thread at a time.
The AtomicMarkableReference
class may seem similar to the AtomicReference
class, but it provides some extra information about the reference object. In particular an AtomicMarkableReference
object maintains an object reference along with a mark bit. The object can be updated atomically, and it is actually a markable reference, since it is a two-value pair of the reference and the boolean mark.
In the example below, we have created an object of a custom class, Person
. We have also created two threads that will both try to access a reference of the person
object. In order to access the reference object, which is created with the AtomicMarkableReference
, we make use of the API methods of the class, as explained below:
- The
AtomicMarkableReference(V initialRef, boolean initialMark)
constructor creates a newAtomicMarkableReference
object with the given initial object and an initial mark. - The
attemptMark(V expectedReference, boolean newMark)
method atomically sets the value of the mark to the given update value if the current reference is equal to the expected reference. - The
compareAndSet(V expectedReference, V newReference, boolean expectedMark, boolean newMark)
method atomically sets the value of both the reference and mark to the given update values if the current reference is equal to the expected reference and the current mark is equal to the expected mark. - The
get(boolean[] markHolder)
method returns the current values of both the reference and the mark, whereas theset(V newReference, boolean newMark)
method unconditionally sets the value of both the reference and mark. - The
getReference()
method returns the current value of the reference, whereasisMarked()
method returns the current value of the mark.
AtomicMarkableReferenceExample
package com.javacodegeeks.snippets.core; import java.util.concurrent.atomic.AtomicMarkableReference; public class AtomicMArkableReferenceExample { private static Person person; private static AtomicMarkableReference<Person> aMRperson; public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(new MyRun1()); Thread t2 = new Thread(new MyRun2()); person = new Person(15); aMRperson = new AtomicMarkableReference<Person>(person, false); System.out.println("Person is " + aMRperson.getReference() + "\nMark: " + aMRperson.isMarked()); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("\nNow Person is " + aMRperson.getReference() + "\nMark: " + aMRperson.isMarked()); } static class MyRun1 implements Runnable { public void run() { for (int i = 0; i <= 5; i++) { aMRperson.getReference().setAge(person.getAge()+1); aMRperson.compareAndSet(new Person(18), new Person(18), false, true); aMRperson.set(aMRperson.getReference(), true); System.out.println("\n" + Thread.currentThread().getName() + " ---> " + aMRperson.getReference().toString() + "\nMark: " + aMRperson.isMarked()); } } } static class MyRun2 implements Runnable { public void run() { for (int i = 0; i <= 5; i++) { aMRperson.getReference().setAge(person.getAge() - 1); aMRperson.attemptMark(new Person(40), true); System.out.println("\n" + Thread.currentThread().getName() + " ---> " + aMRperson.getReference().toString()+ "\nMark: " + aMRperson.isMarked()); } } } static class Person { private int age; public Person(int age) { this.age = age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person age is " + this.age; } } }
If you run the example, the output will be something like the one below:
Output
Person is Person age is 15 Mark: false Thread-0 ---> Person age is 15 Mark: true Thread-1 ---> Person age is 15 Mark: true Thread-0 ---> Person age is 16 Mark: true Thread-1 ---> Person age is 15 Mark: true Thread-0 ---> Person age is 16 Mark: true Thread-1 ---> Person age is 15 Mark: true Thread-0 ---> Person age is 16 Mark: true Thread-1 ---> Person age is 15 Mark: true Thread-0 ---> Person age is 16 Mark: true Thread-1 ---> Person age is 15 Mark: true Thread-0 ---> Person age is 16 Mark: true Thread-1 ---> Person age is 15 Mark: true Now Person is Person age is 15 Mark: true
This was an example of the AtomicMarkableReference
class of Java.
You can download the full source code of this example here: JavaAtomicMarkableReferenceExample
Hi! Thanks for the useful explanation.
I’m a little confused of example.
From documentation (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html): “…this package contains Updater classes that can be used to obtain compareAndSet operations on any selected volatile field of any selected class.”
So, shouldn’t field age be volatile?