After my post ‘ThreadLocal, what is it?’ I would write some words about the java.util.concurrent.atomic package that contains a small toolkit of classes supporting lock-free thread-safe programming on single variables.

We will compare in this example the 3 types of shared counters:
– a simple counter without synchronization or lock,
– an advanced counter with synchronization,
– an atomic counter without synchronization or lock but with AtomicInteger,

Here, a classe defining 3 static counters accessed by several threads:

public class MyValueData {

	// Counter n°1
	private Integer counterSimple = new Integer(0);
	
	// Counter n°2
	private Integer counterAdvanced = new Integer(0);
	
	// Counter n°3
	private AtomicInteger counterAtomic = new AtomicInteger(0);

	public MyValueData(){ }

	public synchronized Integer getCounterAdvanced() {
		return counterAdvanced;
	}

	public Integer getCounterSimple() {
		return counterSimple;
	}

	public Integer getCounterAtomic() {
		return counterAtomic.get();
	}

	public void incrementCounterSimple() {
		this.counterSimple++;
	}
	
	public synchronized void incrementCounterAdvanced() {
		this.counterAdvanced++;
	}
	
	public void incrementCounterAtomic() {
		this.counterAtomic.getAndIncrement();
	}
		
}

Then, we define a Runnable which:
1- starts and sleeps during a 1100ms,
2- increments the 3 counters,
3- repeats the steps 1 and 2 until the counter n°1 is equal or greater than 100;

public class MyTask implements Runnable {

	private int sleepTime; // random sleep time for thread   
	private String threadName; // name of thread   
	
	private MyValueData myValueData;
	
	public MyTask(String name, MyValueData myValueData) {
		// set name of thread
		this.threadName = name;
		this.sleepTime = 1100;
		this.myValueData = myValueData;
	}

	public void run() {
		try{
			while(this.myValueData.getCounterAdvanced()<100){
				// put thread to sleep for sleepTime amount of time
				System.out.printf("%s with sleep for %d ms: counterSimple=%d, counterAdvanced=%d, counterAtomic=%d,  \n", this.threadName, this.sleepTime, this.myValueData.getCounterSimple(), this.myValueData.getCounterAdvanced(), this.myValueData.getCounterAtomic());
				// put thread to sleep
				Thread.sleep( this.sleepTime );				
				//
				// Increment
				this.myValueData.incrementCounterSimple();
				this.myValueData.incrementCounterAtomic();
				this.myValueData.incrementCounterAdvanced();

			}
		} catch ( InterruptedException exception )  {  
			exception.printStackTrace(); 
		}
		// print thread name
		System.out.printf( "%s done sleeping\n", this.threadName );  
	}
		
}

At last, the main method which will:
– create a instance of ‘MyValueData’ class containing the 3 counters,
– create 3 threads named “threadname_1″, “threadname_2″ and “threadname_3″ with the above instance of ‘MyValueData’,
– execute these 3 threads due to an ExecutorService;

	public static void main(String[] args) {
		
		// create and name each runnable
		MyValueData myValueData = new MyValueData();
		MyTask th1 = new MyTask("threadname_1", myValueData);
		MyTask th2 = new MyTask("threadname_2", myValueData);
		MyTask th3 = new MyTask("threadname_3", myValueData);

		// create ExecutorService to manage threads OR empty (better)
		ExecutorService es = Executors.newFixedThreadPool(3);
		
		// start threads and place in runnable state 
		es.execute(th1);
		es.execute(th2);
		es.execute(th3);

		// shutdown worker threads  
		es.shutdown();
		
	}

…so the ouputs in console would be like the following traces. In these outputs, we could see that the counter n°2 (advanced counter with synchronization) and counter n°3 (atomic counter without synchronization or lock but with AtomicInteger) have the same values corresponding to the number of occurrences done. However, the counter n°1 (simple counter without synchronization or lock) has a different value from the two others because this counter is not protected by a synchronization or lock system.

At the end, the value of these counters are:
– threadname_1 with sleep for 1100 ms: counterSimple=97, counterAdvanced=99, counterAtomic=99,
– threadname_2 with sleep for 1100 ms: counterSimple=96, counterAdvanced=98, counterAtomic=98,
– threadname_3 with sleep for 1100 ms: counterSimple=95, counterAdvanced=97, counterAtomic=97,

threadname_2 with sleep for 1100 ms: counterSimple=0, counterAdvanced=0, counterAtomic=0,  
threadname_3 with sleep for 1100 ms: counterSimple=0, counterAdvanced=0, counterAtomic=0,  
threadname_1 with sleep for 1100 ms: counterSimple=0, counterAdvanced=0, counterAtomic=0,  
threadname_3 with sleep for 1100 ms: counterSimple=2, counterAdvanced=1, counterAtomic=2,  
threadname_1 with sleep for 1100 ms: counterSimple=3, counterAdvanced=3, counterAtomic=3,  
threadname_2 with sleep for 1100 ms: counterSimple=2, counterAdvanced=2, counterAtomic=2,  
threadname_1 with sleep for 1100 ms: counterSimple=4, counterAdvanced=4, counterAtomic=4,  
threadname_3 with sleep for 1100 ms: counterSimple=6, counterAdvanced=6, counterAtomic=6,  
threadname_2 with sleep for 1100 ms: counterSimple=5, counterAdvanced=5, counterAtomic=5,  
threadname_3 with sleep for 1100 ms: counterSimple=7, counterAdvanced=7, counterAtomic=7,  
threadname_1 with sleep for 1100 ms: counterSimple=9, counterAdvanced=9, counterAtomic=9,  
threadname_2 with sleep for 1100 ms: counterSimple=8, counterAdvanced=8, counterAtomic=8,  
threadname_2 with sleep for 1100 ms: counterSimple=10, counterAdvanced=10, counterAtomic=10,  
threadname_1 with sleep for 1100 ms: counterSimple=11, counterAdvanced=11, counterAtomic=11,  
threadname_3 with sleep for 1100 ms: counterSimple=12, counterAdvanced=12, counterAtomic=12,  
threadname_2 with sleep for 1100 ms: counterSimple=13, counterAdvanced=13, counterAtomic=13,  
threadname_3 with sleep for 1100 ms: counterSimple=14, counterAdvanced=14, counterAtomic=14,  
threadname_1 with sleep for 1100 ms: counterSimple=15, counterAdvanced=15, counterAtomic=15,  
threadname_1 with sleep for 1100 ms: counterSimple=16, counterAdvanced=16, counterAtomic=16,  
threadname_3 with sleep for 1100 ms: counterSimple=18, counterAdvanced=18, counterAtomic=18,  
threadname_2 with sleep for 1100 ms: counterSimple=17, counterAdvanced=17, counterAtomic=17,  
threadname_1 with sleep for 1100 ms: counterSimple=19, counterAdvanced=19, counterAtomic=19,  
threadname_3 with sleep for 1100 ms: counterSimple=21, counterAdvanced=21, counterAtomic=21,  
threadname_2 with sleep for 1100 ms: counterSimple=20, counterAdvanced=20, counterAtomic=20,  
threadname_3 with sleep for 1100 ms: counterSimple=22, counterAdvanced=22, counterAtomic=22,  
threadname_1 with sleep for 1100 ms: counterSimple=24, counterAdvanced=24, counterAtomic=24,  
threadname_2 with sleep for 1100 ms: counterSimple=23, counterAdvanced=23, counterAtomic=23,  
threadname_3 with sleep for 1100 ms: counterSimple=25, counterAdvanced=25, counterAtomic=25,  
threadname_1 with sleep for 1100 ms: counterSimple=27, counterAdvanced=27, counterAtomic=27,  
threadname_2 with sleep for 1100 ms: counterSimple=26, counterAdvanced=26, counterAtomic=26,  
threadname_2 with sleep for 1100 ms: counterSimple=29, counterAdvanced=28, counterAtomic=28,  
threadname_1 with sleep for 1100 ms: counterSimple=29, counterAdvanced=29, counterAtomic=29,  
threadname_3 with sleep for 1100 ms: counterSimple=30, counterAdvanced=30, counterAtomic=30,  
threadname_2 with sleep for 1100 ms: counterSimple=31, counterAdvanced=31, counterAtomic=31,  
threadname_3 with sleep for 1100 ms: counterSimple=32, counterAdvanced=32, counterAtomic=32,  
threadname_1 with sleep for 1100 ms: counterSimple=33, counterAdvanced=33, counterAtomic=33,  
threadname_2 with sleep for 1100 ms: counterSimple=34, counterAdvanced=34, counterAtomic=34,  
threadname_1 with sleep for 1100 ms: counterSimple=36, counterAdvanced=36, counterAtomic=36,  
threadname_3 with sleep for 1100 ms: counterSimple=35, counterAdvanced=35, counterAtomic=35,  
threadname_2 with sleep for 1100 ms: counterSimple=37, counterAdvanced=37, counterAtomic=37,  
threadname_1 with sleep for 1100 ms: counterSimple=38, counterAdvanced=38, counterAtomic=38,  
threadname_3 with sleep for 1100 ms: counterSimple=39, counterAdvanced=39, counterAtomic=39,  
threadname_2 with sleep for 1100 ms: counterSimple=40, counterAdvanced=40, counterAtomic=40,  
threadname_3 with sleep for 1100 ms: counterSimple=42, counterAdvanced=42, counterAtomic=42,  
threadname_1 with sleep for 1100 ms: counterSimple=41, counterAdvanced=41, counterAtomic=41,  
threadname_2 with sleep for 1100 ms: counterSimple=43, counterAdvanced=43, counterAtomic=43,  
threadname_1 with sleep for 1100 ms: counterSimple=44, counterAdvanced=45, counterAtomic=45,  
threadname_3 with sleep for 1100 ms: counterSimple=43, counterAdvanced=44, counterAtomic=44,  
threadname_3 with sleep for 1100 ms: counterSimple=45, counterAdvanced=46, counterAtomic=46,  
threadname_1 with sleep for 1100 ms: counterSimple=47, counterAdvanced=48, counterAtomic=48,  
threadname_2 with sleep for 1100 ms: counterSimple=46, counterAdvanced=47, counterAtomic=47,  
threadname_2 with sleep for 1100 ms: counterSimple=48, counterAdvanced=49, counterAtomic=49,  
threadname_3 with sleep for 1100 ms: counterSimple=49, counterAdvanced=50, counterAtomic=50,  
threadname_1 with sleep for 1100 ms: counterSimple=50, counterAdvanced=51, counterAtomic=51,  
threadname_2 with sleep for 1100 ms: counterSimple=51, counterAdvanced=52, counterAtomic=52,  
threadname_1 with sleep for 1100 ms: counterSimple=52, counterAdvanced=53, counterAtomic=53,  
threadname_3 with sleep for 1100 ms: counterSimple=53, counterAdvanced=54, counterAtomic=54,  
threadname_2 with sleep for 1100 ms: counterSimple=54, counterAdvanced=55, counterAtomic=55,  
threadname_1 with sleep for 1100 ms: counterSimple=56, counterAdvanced=57, counterAtomic=57,  
threadname_3 with sleep for 1100 ms: counterSimple=55, counterAdvanced=56, counterAtomic=56,  
threadname_2 with sleep for 1100 ms: counterSimple=57, counterAdvanced=58, counterAtomic=58,  
threadname_1 with sleep for 1100 ms: counterSimple=59, counterAdvanced=60, counterAtomic=60,  
threadname_3 with sleep for 1100 ms: counterSimple=58, counterAdvanced=59, counterAtomic=59,  
threadname_1 with sleep for 1100 ms: counterSimple=60, counterAdvanced=61, counterAtomic=61,  
threadname_3 with sleep for 1100 ms: counterSimple=62, counterAdvanced=63, counterAtomic=63,  
threadname_2 with sleep for 1100 ms: counterSimple=61, counterAdvanced=62, counterAtomic=62,  
threadname_2 with sleep for 1100 ms: counterSimple=63, counterAdvanced=64, counterAtomic=64,  
threadname_1 with sleep for 1100 ms: counterSimple=65, counterAdvanced=66, counterAtomic=66,  
threadname_3 with sleep for 1100 ms: counterSimple=64, counterAdvanced=65, counterAtomic=65,  
threadname_2 with sleep for 1100 ms: counterSimple=66, counterAdvanced=67, counterAtomic=67,  
threadname_3 with sleep for 1100 ms: counterSimple=67, counterAdvanced=68, counterAtomic=68,  
threadname_1 with sleep for 1100 ms: counterSimple=68, counterAdvanced=69, counterAtomic=69,  
threadname_2 with sleep for 1100 ms: counterSimple=69, counterAdvanced=70, counterAtomic=70,  
threadname_3 with sleep for 1100 ms: counterSimple=70, counterAdvanced=71, counterAtomic=71,  
threadname_1 with sleep for 1100 ms: counterSimple=71, counterAdvanced=72, counterAtomic=72,  
threadname_3 with sleep for 1100 ms: counterSimple=72, counterAdvanced=73, counterAtomic=73,  
threadname_1 with sleep for 1100 ms: counterSimple=74, counterAdvanced=75, counterAtomic=75,  
threadname_2 with sleep for 1100 ms: counterSimple=73, counterAdvanced=74, counterAtomic=74,  
threadname_3 with sleep for 1100 ms: counterSimple=75, counterAdvanced=76, counterAtomic=76,  
threadname_1 with sleep for 1100 ms: counterSimple=77, counterAdvanced=78, counterAtomic=78,  
threadname_2 with sleep for 1100 ms: counterSimple=76, counterAdvanced=77, counterAtomic=77,  
threadname_2 with sleep for 1100 ms: counterSimple=78, counterAdvanced=79, counterAtomic=79,  
threadname_3 with sleep for 1100 ms: counterSimple=79, counterAdvanced=81, counterAtomic=81,  
threadname_1 with sleep for 1100 ms: counterSimple=78, counterAdvanced=80, counterAtomic=80,  
threadname_3 with sleep for 1100 ms: counterSimple=80, counterAdvanced=82, counterAtomic=82,  
threadname_2 with sleep for 1100 ms: counterSimple=81, counterAdvanced=83, counterAtomic=83,  
threadname_1 with sleep for 1100 ms: counterSimple=82, counterAdvanced=84, counterAtomic=84,  
threadname_2 with sleep for 1100 ms: counterSimple=83, counterAdvanced=85, counterAtomic=85,  
threadname_1 with sleep for 1100 ms: counterSimple=85, counterAdvanced=87, counterAtomic=87,  
threadname_3 with sleep for 1100 ms: counterSimple=84, counterAdvanced=86, counterAtomic=86,  
threadname_2 with sleep for 1100 ms: counterSimple=86, counterAdvanced=88, counterAtomic=88,  
threadname_1 with sleep for 1100 ms: counterSimple=87, counterAdvanced=89, counterAtomic=89,  
threadname_3 with sleep for 1100 ms: counterSimple=88, counterAdvanced=90, counterAtomic=90,  
threadname_3 with sleep for 1100 ms: counterSimple=89, counterAdvanced=91, counterAtomic=91,  
threadname_1 with sleep for 1100 ms: counterSimple=91, counterAdvanced=93, counterAtomic=93,  
threadname_2 with sleep for 1100 ms: counterSimple=90, counterAdvanced=92, counterAtomic=92,  
threadname_2 with sleep for 1100 ms: counterSimple=92, counterAdvanced=94, counterAtomic=94,  
threadname_1 with sleep for 1100 ms: counterSimple=94, counterAdvanced=96, counterAtomic=96,  
threadname_3 with sleep for 1100 ms: counterSimple=93, counterAdvanced=95, counterAtomic=95,  
threadname_3 with sleep for 1100 ms: counterSimple=95, counterAdvanced=97, counterAtomic=97,  
threadname_1 with sleep for 1100 ms: counterSimple=97, counterAdvanced=99, counterAtomic=99,  
threadname_2 with sleep for 1100 ms: counterSimple=96, counterAdvanced=98, counterAtomic=98,  
threadname_2 done sleeping
threadname_1 done sleeping
threadname_3 done sleeping

Conclusion
In this post, we could see an use case of the AtomicInteger class which is to able to share a counter without synchronization or lock among several threads.

Note: There is also the AtomicLong class 😉

Best regards,