Created
September 30, 2013 11:19
-
-
Save eleco/6762385 to your computer and use it in GitHub Desktop.
Synchronized vs AtomicReference
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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