Skip to content

Instantly share code, notes, and snippets.

@eleco
Created September 30, 2013 11:19
Show Gist options
  • Save eleco/6762385 to your computer and use it in GitHub Desktop.
Save eleco/6762385 to your computer and use it in GitHub Desktop.
Synchronized vs AtomicReference
import com.google.common.base.Stopwatch;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import static com.google.common.collect.Lists.newArrayList;
public class MultithreadTest {
public static void main(String... args) throws InterruptedException {
List<AccountDate> accountDates = newArrayList(new SimpleAccountDate(), new AccountDateSynchronized(), new AccountDateAtomicRef());
final int poolSize = 20;
final int maxCounter = (1000 * 1000) / poolSize;
for (AccountDate accountDate : accountDates) {
ExecutorService exec = Executors.newFixedThreadPool(poolSize);
Stopwatch stopwatch = new Stopwatch().start();
long initialTime = accountDate.readTime();
for (int j = 0; j < poolSize; j++) {
exec.submit(new AccountModifier(accountDate, maxCounter));
}
exec.shutdown();
exec.awaitTermination(10, TimeUnit.SECONDS);
stopwatch.stop();
System.out.println(accountDate.toString() + " in " + stopwatch.elapsed(TimeUnit.MILLISECONDS) + " ms " +
((accountDate.readTime() != initialTime + maxCounter * poolSize) ? " race condition" : " OK"));
}
}
}
class AccountModifier implements Callable<Void> {
private int counter = 0;
private final int maxCounter;
private AccountDate account;
AccountModifier(AccountDate account, int maxCounter) {
this.account = account;
this.maxCounter = maxCounter;
}
@Override
public Void call() throws Exception {
while (counter++ < maxCounter) {
account.writeTime(1);
}
return null;
}
}
abstract class AccountDate {
Date date = new Date();
long readTime() {
return date.getTime();
}
abstract void writeTime(int i);
@Override
public String toString() {
return this.getClass().getName();
}
}
class SimpleAccountDate extends AccountDate {
@Override
public void writeTime(int increment) {
date.setTime(date.getTime() + increment);
}
}
class AccountDateSynchronized extends AccountDate {
@Override
public synchronized void writeTime(int increment) {
date.setTime(date.getTime() + increment);
}
@Override
public synchronized long readTime() {
return date.getTime();
}
}
class AccountDateAtomicRef extends AccountDate {
AtomicReference<Date> atomicRefDate = new AtomicReference<Date>(date);
@Override
public long readTime() {
return atomicRefDate.get().getTime();
}
@Override
public void writeTime(int increment) {
for (; ; ) {
Date oldDate = atomicRefDate.get();
if (atomicRefDate.compareAndSet(oldDate, new Date(oldDate.getTime() + increment))) return;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment