import java.util.Arrays; import java.util.Random; public class AtomicUpdates { public static class Buckets { private final int[] data; public Buckets(int[] data) { this.data = data.clone(); } public int getBucket(int index) { synchronized (data) { return data[index]; } } public int transfer(int srcBucketIndex, int destBucketIndex, int amount) { if (amount == 0) return 0; // Negative transfers will happen in the opposite direction if (amount < 0) { int tempIndex = srcBucketIndex; srcBucketIndex = destBucketIndex; destBucketIndex = tempIndex; amount = -amount; } synchronized (data) { if (amount > data[srcBucketIndex]) amount = data[srcBucketIndex]; if (amount <= 0) return 0; data[srcBucketIndex] -= amount; data[destBucketIndex] += amount; return amount; } } public int[] getBuckets() { synchronized (data) { return data.clone(); } } } public static int getTotal(int[] values) { int totalValue = 0; for (int i = values.length - 1; i >= 0; i--) totalValue += values[i]; return totalValue; } public static void main(String[] args) { final int NUM_BUCKETS = 10; Random rnd = new Random(); final int[] values = new int[NUM_BUCKETS]; for (int i = 0; i < values.length; i++) values[i] = rnd.nextInt(10); System.out.println("Initial Array: " + getTotal(values) + " " + Arrays.toString(values)); final Buckets buckets = new Buckets(values); new Thread(new Runnable() { public void run() { Random r = new Random(); while (true) { int srcBucketIndex = r.nextInt(NUM_BUCKETS); int destBucketIndex = r.nextInt(NUM_BUCKETS); int amount = (buckets.getBucket(srcBucketIndex) - buckets.getBucket(destBucketIndex)) >> 1; if (amount != 0) buckets.transfer(srcBucketIndex, destBucketIndex, amount); } } } ).start(); new Thread(new Runnable() { public void run() { Random r = new Random(); while (true) { int srcBucketIndex = r.nextInt(NUM_BUCKETS); int destBucketIndex = r.nextInt(NUM_BUCKETS); int srcBucketAmount = buckets.getBucket(srcBucketIndex); int destBucketAmount = buckets.getBucket(destBucketIndex); int amount = r.nextInt(srcBucketAmount + destBucketAmount + 1) - destBucketAmount; if (amount != 0) buckets.transfer(srcBucketIndex, destBucketIndex, amount); } } } ).start(); while (true) { long nextPrintTime = System.currentTimeMillis() + 3000; long curTime; while ((curTime = System.currentTimeMillis()) < nextPrintTime) { try { Thread.sleep(nextPrintTime - curTime); } catch (InterruptedException e) { } } int[] bucketValues = buckets.getBuckets(); System.out.println("Current values: " + getTotal(bucketValues) + " " + Arrays.toString(bucketValues)); } } }