user3117840
user3117840

Reputation:

How to invoke two threads at same time?

I am trying to write Thread Interference Example.

Below is my code:

class Counter {
    private int c = 0;

    public void increment() {
        c++;
    }

    public void decrement() {
        c--;
    }

    public int value() {
        return c;
    }    
}

Suppose Thread A invokes increment at about the same time Thread B invokes decrement. How to implement this one.

Upvotes: 3

Views: 225

Answers (3)

Narendra Pathai
Narendra Pathai

Reputation: 42005

Now in this example if you try to execute and the output false shows interference.

How it works:

Both the Runnables keep a thread local count which is incremented for each invocation of increment() and decrement(). So after execution for some amount of time if we try to validate the values

Then you can say that:

value of Counter = invocation of increment() - invocation of decrement().

But when you try to verify this at the end of execution you get false. Which shows that the actual counter value was not as expected.

public static void main(String[] args) throws InterruptedException
{
        Counter c = new Counter();
        IncrementingRunnable incRunnable = new IncrementingRunnable(c);
        DecrementingRunnable decRunnable = new DecrementingRunnable(c);

        Thread tA = new Thread(incRunnable);
        Thread tB = new Thread(decRunnable);

        tA.start();tB.start();

        Thread.sleep(10000);
        stop = true;

        tA.join();
        tB.join();

        //verify value
        int actualCount = c.c;
        int expectedCount = incRunnable.count - decRunnable.count;
        System.out.println(actualCount == expectedCount);
}


 public static volatile boolean stop = false;

static class IncrementingRunnable implements Runnable{
      volatile int count = 0;
      private Counter counter;

      public IncrementingRunnable(Counter c) {
        this.counter = c;
      }
      @Override
      public void run() {
            while(!stop){
                counter.increment();
                count++;
            }
      }
}

static class DecrementingRunnable implements Runnable{
      volatile int count = 0;
      private Counter counter;

      public DecrementingRunnable(Counter c) {
        this.counter = c;
      }
      @Override
      public void run() {
          while(!stop){
            counter.decrement();
            count++;
        }
      }
}

Now try changing the primitive c in Counter to AtomicInteger and see the output again. You will find that now the output is true.

Upvotes: 0

Affe
Affe

Reputation: 47994

To get two threads to start executing at the same time you can use a latch. (Which is to say, two threads that become available for execution as close together as possible.) Still for a single increment/decrement each it will probably take many runs to observe an interference. For a repeatable experiment you probably want to call increment/decrement several times in parallel and observe the final value of c.

final Counter counter = new Counter()
final CountDownLatch latch = new CountDownLatch(1);
Thread thread1 = new Thread(new Runnable() {
public void run() {
  latch.await();
  for (int i = 0; i < 100; i++) {
    counter.increment();
  }
}}).start():
Thread thread2 = new Thread(new Runnable() {
public void run() {
  latch.await();
  for (int i = 0; i < 100; i++) {
    counter.decrement();
  }
}}).start():
Thread.sleep(10);//give thread 2 a timeslice to hit the await
latch.countDown();
System.out.println(counter.value()); //non-zero value indicates interference

Upvotes: 1

Evgeniy Dorofeev
Evgeniy Dorofeev

Reputation: 136162

There is not guarantee how they will run it depends on OS scheduler. There is nothing better than this

Thread a = new ThreadA();
Thread b = new ThreadB();
a.start();
b.start();

Upvotes: 2

Related Questions