1

I am trying to understand the ExecutorService and how it will avoid the usage of synchronized keyword. I tried something like this below (avoiding imports to for clarity) which gave wrong results:

public class ReadWebPage
{
   public static void main(String[] args)
   {

      ExecutorService executor = Executors.newFixedThreadPool(5);

      FinTrans ft = new FinTrans ();
      TransThread tt1 = new TransThread (ft, "Deposit Thread");
      TransThread tt2 = new TransThread (ft, "Withdrawal Thread");

      executor.submit(tt2);
      executor.submit(tt1);

      executor.shutdown();
    }
}

class FinTrans
{
   public static String transName;
   public static double amount;
}
class TransThread implements Runnable
{
   private FinTrans ft;
   private String name;
   TransThread (FinTrans ft, String name)
   {
      this.name = name;
      this.ft = ft;
   }
   public String getName(){
  return name;
   }
   public void run ()
   {
      for (int i = 0 ; i < 10 ; i++ )
      {
           if (getName ().equals ("Deposit Thread"))
           {
               ft.transName = "Deposit";
               try
               {
                  Thread.sleep ((int) (Math.random () * 100));
               }
               catch (InterruptedException e)
               {
               }
               ft.amount = 2000.0;
               System.out.println (ft.transName + " " + ft.amount);
           }
           else
           {
               ft.transName = "Withdrawal";
               try
               {
                  Thread.sleep ((int) (Math.random () * 10));
               }
               catch (InterruptedException e)
               {
               }
               ft.amount = 250.0;
               System.out.println (ft.transName + " " + ft.amount);
           }
      }
   }
}

Which gave me the wrong result:

Deposit 250.0          //wrong
Withdrawal 250.0
Withdrawal 250.0
Withdrawal 250.0
Withdrawal 250.0
Withdrawal 250.0
Withdrawal 250.0
Withdrawal 250.0
Withdrawal 250.0
Withdrawal 2000.0      //wrong
Deposit 250.0          //wrong
Deposit 2000.0
Deposit 2000.0
Deposit 2000.0
Deposit 2000.0
Deposit 2000.0
Deposit 2000.0
Deposit 2000.0
Deposit 2000.0
Deposit 2000.0

Could you please explain what is going wrong here? 1. Is it because both the Runnables share the same FinTrans object? 2. Does this mean we need same old synchronize mechanism here too?

I am trying to understand at what situation we can use the ServiceExecutors

Anand

2 Answers 2

2

ExecutorService runs jobs in parallel, but does not automatically make it safe to concurrently access shared state across threads. So, "yes" to both parts of your question.

  1. The problem is caused, in part, by the two runnables sharing the same FinTrans state object.
  2. The other part of the problem is the lack of any synchronization or otherwise atomic guarantees around accesses to that shared state.

The executors are good for submitting tasks asynchronously and being able to check on their status (e.g. have they finished) via the returned Future instances.

Sign up to request clarification or add additional context in comments.

2 Comments

Nor does it guarantee the order of execution, i.e. the order of submissions is not necessarily the order of execution.
Thanks for the answer William and Cascasder!
0

You need to have synchronous blocks, in case of asynchronous processing. If you are trying to emulate bank account, processing in java, you can, for example, use some java concurrent primitives.

With AtomicDouble, you can do it like this:

class FinTrans {
   final private AtomicDouble amount = new AtomicDouble();

   public void debit(double debit) {
      double current = 0;
      double new = 0;
      do {
         current = amount.get();
         new = current + debit;
      } while (!amount.compareAndSet(current, newAmount));
   }

   public void credit(double credit) {
     debit(- credit);
   }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.