Set Max Value Without a Lock Using Cas

2 minute read

tl;dr : I was looking for a way to set the maximum value of a variable but without using locks (because locks suck) this is my rant about it using CAS (compare-and-set operation).

We deal a lot with multi-threading and performance is something which we cannot part with. We needed a way to record the maximum latency for the application. The throughput is about 15-20K requests/second  and we needed to monitor and set the maximum latency value (since the start of the application) amongst other things, without affecting the performance.

here were a bunch of solutions that I found online that used locks, but locks although conceptually simple are performance bottleneck. Naturally, I turned to the Java concurrency package for reference and realized that Doug Lea had this algorithm which he used for AtomicLong.getAndIncrement() which used CAS operations. I used the same algorithm to set the max value and so far it appears to work.

Following is the code I used, with comments, hope it helps !

       /**
	 * Try to update the max value without using a lock.
	 * This method is thread safe.
         *
	 * @param val the values to be updated to, if greater than given atomic.
	 * @param atomic the {@link AtomicLong} to be checked
	 * @return true if updated, false if not updated.
	 */
	public static boolean setMax(final long val, final AtomicLong atomic)
	{
	while (true)
	{
		final long currentMax = atomic.get();

		if (currentMax >= diff)
		{
			/* if the current value is greater than diff we break */
			return false;
		}

		/*
		* Here we check whether other thread has already modified the
		* currentMax value, if yes setSuccess=false or else 
		* setSuccess=true in which case we the following operation 
		* will update the maxLatency value to the diff.
		*/
		final boolean setSuccess = atomic.compareAndSet(currentMax, diff);

		if (setSuccess)
		{
			/*
			* we managed to update the max value, no other thread changed
			* it, we are don here.
			*/
			return true;
		}

		/* some other thread got in the way, go back and do the drill again. */
	}

	}
comments powered by Disqus