-1

I'm trying to use AtomicLong in Multi Threading Environment. My desired result is not working,

public class Account implements Runnable {

    private final AtomicLong amount = new AtomicLong(0);

    public Account(long difference) {
        amount.set(difference);
    }

    public void run() {
        System.out.println("The Balance is : " + amount);
    }
}
public class Examples {
    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(10);
        IntStream.range(0, 100).forEach(i -> service.submit(new Account(i)));
    }
}

I tried to use Read/Write Lock and block level synchronization but no luck. Could please someone spot where am doing mistake?

I output has to be starts from 0,1,2...99.

parrotjack
  • 432
  • 1
  • 6
  • 18

2 Answers2

4

There's no data shared between any of your threads... each creates its own AtomicLong, no sharing. Even if it was shared there would be no guarantee at all that the numbers will print in order. They would not even be a guarantee that all numbers are printed (some of them could be printed more than once).

If I change your code like this:

public static class Account implements Runnable {
    private static final AtomicLong amount = new AtomicLong(0);

    public Account(long difference) {
        amount.set(difference);
    }

    public void run() {
        System.out.println("The Balance is : " + amount);
    }
}

Here's an example of output I get:

The Balance is : 2
The Balance is : 2
The Balance is : 2
The Balance is : 4
The Balance is : 5
The Balance is : 6
The Balance is : 7
The Balance is : 8
The Balance is : 9
The Balance is : 9

The reason is that the following scenario is possible:

  • main thread creates Account(0). This writes 0 to the shared AtomicLong.,
  • Thread-0 starts up
  • main thread creates Account(1). This writes 1 to the shared AtomicLong.
  • Thread-0 prints the value, it's now 1. In this case 0 will never be printed.

The only thing that AtomicLong does guarantee you is that all the writes to the value will always be visible by all threads making a read afterwards.

The properties of atomic variables are detailed in the javadoc (see here).

Dici
  • 25,226
  • 7
  • 41
  • 82
  • 2
    "It's even not guaranteed that all numbers will be printed (some might be printed twice)" I don't understand this statement: why not? (/Why?) An instance of the class is created for every i in the range. – Andy Turner Apr 04 '20 at 17:58
  • 1
    I misread and thought the call to `set` and the call to `get` aren't atomic as they're in two separate methods (the constructor, and the `run` method). But in fact, all instances will be created in the main thread sequentially, only the reads occur in a multithreaded manner, so yes all of them will be printed with no order guarantee. Thanks, will fix :p – Dici Apr 04 '20 at 18:00
  • Thanks for your explanation @Dici and Andy – parrotjack Apr 04 '20 at 18:02
  • @AndyTurner ok, so I revert my reply to your comment but will make the answer clearer. What I meant is that **if** the data was shared, we would not have any guarantee that all numbers are printed it, and I just confirmed this. The reason is that such scenarii are possible: 1) main thread creates `Account(0)`, 2) `Thread-0` starts up 3) main thread creates `Account(1)` (which writes `1` to the shared `AtomicLong`), 4) `Thread-0` prints the value, it's now `1`. In this case `0` will never be printed – Dici Apr 04 '20 at 18:14
0

Maybe you meant something like that:

public class Account implements Runnable {

    private final static AtomicLong seq = new AtomicLong(0);
    private final long amount;

    public Account() {
        amount = seq.getAndIncrement();
    }

    public void run() {
        System.out.println("The Balance is : " + amount);
    }
}

public class Examples {
    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(10);
        IntStream.range(0, 100).forEach(i -> service.submit(new Account()));
    }
}

This will guarantee that each account will get a unique value of amount, but the values could be printed in different order.

ciamej
  • 6,918
  • 2
  • 29
  • 39
  • correct, i tried with this approach also, got order was different. – parrotjack Apr 04 '20 at 18:31
  • @parrotjack Well if you really need the exact order to be preserved then there is no point in using multi-threading. What you want is serial execution - and that's guaranteed straightforwardly by single-threaded execution. – ciamej Apr 04 '20 at 18:54