0

I ran following java code to test multithreading. I would like to make each thread increments the index variable by 1. But following doesn't work.

public class start {
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        Thread[] threadList = new Thread[20];

        for (int i = 0; i < 20; i++) {
            threadList[i] = new worker();
            threadList[i].start();
        }
    }
}

public class worker extends Thread {
    private static int index = 0;

    public static synchronized int getIndex() {
        return index++;
    }

    public void run() {
        index = getIndex();
        System.out.println("Thread Name: "+Thread.currentThread().getName() + "index: "+index);
    }
}

It gives me following result:

Thread Name: Thread-0index: 0
Thread Name: Thread-2index: 0
Thread Name: Thread-4index: 0
Thread Name: Thread-1index: 0
Thread Name: Thread-6index: 0
Thread Name: Thread-8index: 0
Thread Name: Thread-5index: 0
Thread Name: Thread-7index: 0
Thread Name: Thread-3index: 0
Thread Name: Thread-9index: 0
Thread Name: Thread-13index: 0
Thread Name: Thread-11index: 0
Thread Name: Thread-12index: 0
Thread Name: Thread-10index: 0
Thread Name: Thread-14index: 0
Thread Name: Thread-17index: 0
Thread Name: Thread-15index: 0
Thread Name: Thread-19index: 0
Thread Name: Thread-16index: 0
Thread Name: Thread-18index: 0

Index value did not change. How to fix this issue?

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
user537397
  • 47
  • 1
  • 5
  • 3
    `return index++;` is returning the value of `index` and incrementing it afterwards, since you assign it back, you'll get the same old value for index – BeyelerStudios Jan 21 '15 at 14:48
  • annotate your run() method with @Override as you are extending the behaviour of run() method from Parent class Thread. – ha9u63a7 Jan 21 '15 at 14:49

3 Answers3

4

This assignment is resetting the value of index (and is unsynchronized):

index = getIndex();

overriding the effect of the increment operator. A possible solution would be to store the result of getIndex() in a local variable:

final int i = getIndex();
System.out.println("Thread Name: "                  +
                   Thread.currentThread().getName() +
                   "index: "                        +
                   i);

"implements Runnable" vs. "extends Thread"

Community
  • 1
  • 1
hmjd
  • 120,187
  • 20
  • 207
  • 252
0

For this simple program to increment index number for each Thread invocation, AtomicInteger variable would be suffice.

An int value that may be updated atomically. See the java.util.concurrent.atomic package specification for description of the properties of atomic variables. An AtomicInteger is used in applications such as atomically incremented counters, and cannot be used as a replacement for an Integer.

Corrected code:

import java.util.concurrent.atomic.AtomicInteger;

public class ThreadDemo {
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        Thread[] threadList = new Thread[20];

        for (int i = 0; i < 20; i++) {
            threadList[i] = new worker();
            threadList[i].start();
        }
    }
}

class worker extends Thread {
    private static AtomicInteger index = new AtomicInteger(0);

    private int getIntValueOfIndex(){
        return index.incrementAndGet();
    }

    public void run() {
       System.out.println("Thread Name: "+Thread.currentThread().getName() + "index: "+getIntValueOfIndex());
    }
}
Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
-1

index = getIndex(); is not atomic. Reads and writes to shared data must be synchronized.

Delete this line and change +index in run() to getIndex() and see what happens.

Joe
  • 1