When two threads update shared data, a small synchronized method keeps the update atomic and replay shows the worker calls by thread color.

Counter Updates

SharedCounter.java
public class SharedCounter {
    static class Counter {
        private int value;

        synchronized void add(int delta) {
            value = value + delta;
            System.out.println("value=" + value);
        }

        int get() {
            return value;
        }
    }

    static class AddTask implements Runnable {
        private final Counter counter;
        private final int delta;
        private final int repeats;

        AddTask(Counter counter, int delta, int repeats) {
            this.counter = counter;
            this.delta = delta;
            this.repeats = repeats;
        }

        @Override
        public void run() {
            for (int i = 0; i < repeats; i++) {
                counter.add(delta);
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        int repeats = ;
        Counter counter = new Counter();
        Thread plusOne = new Thread(new AddTask(counter, 1, repeats));
        Thread plusTen = new Thread(new AddTask(counter, 10, repeats));

        plusOne.start();
        plusTen.start();
        plusOne.join();
        plusTen.join();

        System.out.println("final=" + counter.get());
    }
}
public class SharedCounter {
    static class Counter {
        private int value;

        synchronized void add(int delta) {
            value = value + delta;
            System.out.println("value=" + value);
        }

        int get() {
            return value;
        }
    }

    static class AddTask implements Runnable {
        private final Counter counter;
        private final int delta;
        private final int repeats;

        AddTask(Counter counter, int delta, int repeats) {
            this.counter = counter;
            this.delta = delta;
            this.repeats = repeats;
        }

        @Override
        public void run() {
            for (int i = 0; i < repeats; i++) {
                counter.add(delta);
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        int repeats = ;
        Counter counter = new Counter();
        Thread plusOne = new Thread(new AddTask(counter, 1, repeats));
        Thread plusTen = new Thread(new AddTask(counter, 10, repeats));

        plusOne.start();
        plusTen.start();
        plusOne.join();
        plusTen.join();

        System.out.println("final=" + counter.get());
    }
}
public class SharedCounter {
    static class Counter {
        private int value;

        synchronized void add(int delta) {
            value = value + delta;
            System.out.println("value=" + value);
        }

        int get() {
            return value;
        }
    }

    static class AddTask implements Runnable {
        private final Counter counter;
        private final int delta;
        private final int repeats;

        AddTask(Counter counter, int delta, int repeats) {
            this.counter = counter;
            this.delta = delta;
            this.repeats = repeats;
        }

        @Override
        public void run() {
            for (int i = 0; i < repeats; i++) {
                counter.add(delta);
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        int repeats = ;
        Counter counter = new Counter();
        Thread plusOne = new Thread(new AddTask(counter, 1, repeats));
        Thread plusTen = new Thread(new AddTask(counter, 10, repeats));

        plusOne.start();
        plusTen.start();
        plusOne.join();
        plusTen.join();

        System.out.println("final=" + counter.get());
    }
}
synchronized A `synchronized` method lets one thread at a time enter that method for the same object.
shared state Shared state is data that more than one thread can read or write.