Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to maintain state for each thread separately

I have a field int x which is supposed to be accessed from many threads at the same time. I want x to have a separate copy per thread, each starting out at its original value. I tried to do this using the volatile keyword, but each new thread still modifies x for other threads.

Here is a code example:

public class StackOverflowThread0 {

    public StackOverflowThread0() {
        new A().start();
    }

    public static void main(String[] args) {
        new StackOverflowThread0();
    }

    volatile int x = 0;//<--keep original for each thread?

    class A extends Thread {

        @Override
        public void run() {
            try {
                while (true) {
                    getT().start();

                    Thread.sleep(1000);
                }
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
    }

    Thread getT() {
        Thread t = new Thread() {

            @Override
            public void run() {
                x++;

                for (int i = 0; i < 100; i++) {
                    try {
                        System.out.println("x=" + x + " | thread id=" + Thread.currentThread().getId() + "| 100*x+x=" + (100 * x + x));
                        Thread.sleep(100);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
                interrupt();
            }
        };
        return t;
    }
}

the output is :

x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101 //thread 10 has x field value as 1
x=2 | thread id=11| 100*x+x=202 //thread 11 modifies x field to 2
x=2 | thread id=10| 100*x+x=202 //thread 10 lost x value as 1 :(

etc...

How do I keep a separate x value for each thread, or is there a more optimal way to solve the task?

like image 238
user390525 Avatar asked Jul 05 '15 22:07

user390525


2 Answers

The ThreadLocal class can make this happen for you. It maintains a variable that is different for each thread that accesses it. In other words, each thread gets its own unique copy of the variable.

Check out the following changes to your code:

//Initialisation of the variable. Here an initial value of zero is assigned.
ThreadLocal<Integer> x = ThreadLocal.withInitial(()-> 0);

//Incrementing the value by one:
x.set(x.get() + 1);

//Outputting the result:
System.out.println("x=" + x.get() + " | thread id=" 
                            + Thread.currentThread().getId() + "| 100*x+x=" + (100 * x.get() + x.get()));

Edit: For those using 1.7, there is indeed a way to use ThreadLocal without the lambda expression. You'll have to override the initialValue() method, though.

ThreadLocal<Integer> x = new ThreadLocal<Integer>() {
    @Override
    protected Integer initialValue() {
        return 0;
    }
};
like image 128
Reinstate Monica Avatar answered Nov 12 '22 02:11

Reinstate Monica


Alternative to Thread Local Storage, you can keep your x variable on your call stack. Of course that depends on how you use x; you may actually need your variable on the heap. And in that case you're better off with ThreadLocal.

Threads all share a heap, but have their own stack.

Which means any variables that are kept on the stack are immediately thread local.

like image 35
kervin Avatar answered Nov 12 '22 01:11

kervin