Skip to content

Instantly share code, notes, and snippets.

@qbosen
Last active July 23, 2020 07:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save qbosen/23b8cdb0bcda2f350da496fd1c6b076b to your computer and use it in GitHub Desktop.
Save qbosen/23b8cdb0bcda2f350da496fd1c6b076b to your computer and use it in GitHub Desktop.
cas demo
import sun.misc.Contended;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
class Scratch {
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(10);
final CAS cas = new CAS();
Runnable addFortyFive = () -> IntStream.range(0, 10).forEach(cas::addAndGet);
IntStream.range(0, 100).forEach(x -> executorService.execute(addFortyFive));
executorService.shutdown();
executorService.awaitTermination(2, TimeUnit.SECONDS);
System.out.println(cas.get());
if (4500 != cas.get()) throw new AssertionError();
}
static class CAS {
@Contended
private volatile int x = 0;
public int addAndGet(int n) {
while (true) {
int curr = get();
int next = curr + n;
if (compareAndSet(curr, next)) {
return next;
}
}
}
public int get() {
return this.x;
}
private static final Unsafe unsafe;
private static final long valueOffset;
static {
try {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
unsafe = (Unsafe) theUnsafe.get(null);
valueOffset = unsafe.objectFieldOffset(CAS.class.getDeclaredField("x"));
} catch (Exception e) {
throw new Error(e);
}
}
private boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment