Question

Can anyone confirm below statement?

Method Arguments and Local Variable declared inside a method is Thread safe; both are exclusive for each invocation of the Thread.

On the other hand Global Variable is shared.

For instance

class MyThread implements Runnable{

    int _tmp = 10;      //SHARED BETWEEN t1, t2, t3, and so on

    public void run(){

        testThreadConcurrency(arg); // arg  is EXCLUSIVE FOR ALL invocation of testThreadConcurrency
    }

    public void testThreadConcurrency (int num){

        int tmp = 10;   //EXCLUSIVE FOR ALL invocation of testThreadConcurrency()

    }
}


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

        MyThread _runn = new MyThread();

        Thread t1 = new Thread(_runn,"t1");
        Thread t2 = new Thread(_runn,"t2");
        Thread t3 = new Thread(_runn,"t3");
        t1.start();
        t2.start();             
        t3.start()
}

**

Please check the output of below program which prove that Global variables are SHARED

**

public class ThreadDemo {

    static Object _lock = new Object();

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

        MyThread _runn = new MyThread();

        Thread t1 = new Thread(_runn,"t1");
        Thread t2 = new Thread(_runn,"t2");
        Thread t3 = new Thread(_runn,"t3");
        t1.start();
        try {Thread.sleep(300);} catch (InterruptedException e1) {}
        t2.start(); 
        try {Thread.sleep(300);} catch (InterruptedException e1) {}
        t3.start(); 

        try {Thread.sleep(300);} catch (InterruptedException e1) {}
        synchronized(ThreadDemo._lock){ThreadDemo._lock.notify();}

        try {Thread.sleep(300);} catch (InterruptedException e1) {}
        synchronized(ThreadDemo._lock){ThreadDemo._lock.notify();}


        try {Thread.sleep(300);} catch (InterruptedException e1) {}
        synchronized(ThreadDemo._lock){ThreadDemo._lock.notify();}


    }

}

class MyThread implements Runnable{

    int _tmp = 10;

    public void run(){

        testTestConcurrency();
    }

    public void testTestConcurrency(){

        if(Thread.currentThread().getName().equals("t2"))
        {
            _tmp = 20;          
        }

        synchronized(ThreadDemo._lock){try {ThreadDemo._lock.wait();} catch (InterruptedException e) {}}

        System.out.println("_tmp = "+_tmp+"|"+Thread.currentThread().getName());


    }
}
Was it helpful?

Solution 2

Not exactly:

T1's _tmp is not shared with T2's _tmp since they are distinct MyThread's instances (not class' variables but instance's variables).

Indeed, you reinstantiate the whole class each time you create a thread:

new MyThread

It would be different if attributes were actually class variables:

static int _tmp = 10;

In this case you might need some synchronization mechanism (synchronized block, or volatile keyword or anything else adapted to the situation)

I would rephrase it to:

Method Arguments and Local Variable declared inside a method is Thread safe; both are exclusive for each invocation of the Thread.

However, a same instance of any class dealing with one or more global variables shares those ones among hitting threads.

It is a best practice to avoid the maximum of shared instances among threads, to avoid the need to synchronize everything (as long as performance/memory isn't too hurt).

Thus your code snippet follows the best practice :)

-----------COMMENT ABOUT YOUR ADDED CODE SNIPPET--------------:

MyThread _runn = new MyThread();  //you are using the same instance here ! delete this line

So, indeed, in this case the attribute would be share if you reuse this instance when declaring each thread:

Thread t1 = new Thread(_runn,"t1");
Thread t2 = new Thread(_runn,"t2");
Thread t3 = new Thread(_runn,"t3");

Replace by just:

Thread t1 = new Thread(new MyThread(), "t1"); //a new MyThread instance for each thread !
Thread t2 = new Thread(new MyThread(), "t2");
Thread t3 = new Thread(new MyThread(), "t3");

Will output (as expected :)):

_tmp = 10|t3
_tmp = 10|t1
_tmp = 20|t2

OTHER TIPS

Be careful! Arguments and variables are not objects. Suppose that several threads each enter a method that manipulates a List:

public Foo mumbler(List<Bar> barList) {
    ...
}

Each invocation of the method has its own unique barList variable. It can not be accessed by any other thread, but if all of those variables hold references to the same List object, then the threads still can (and probably will) corrupt the List if they don't prevent it by mutual exclusion or by some other means.

Edit:

I forgot Java pass primitives as a CallByValue but use CallByReference in case of References....

A better way to say that is, Java passes object references by value:

In C++ you could write this: (not that you'd ever want to write it :-)

pushValueOnStack(my_type_t value, struct node &top) {
    struct node new_node = malloc(sizeof(*new_node));
    new_node->value = value;
    new_node->next = top;
    top = new_node;
}

If you had a local variable, myStack, and you called pushValueOnStack(someValue, myStack), it would actually change your local variable to point the stack's new top node. That's call-by-reference. That never happens in Java.

Method Arguments and Local Variable declared inside a method is Thread safe; both are exclusive for each invocation of the Thread.

Each invocation of the method. There is no such thing as 'invocation of the Thread', and if there was, it isn't sufficiently inclusive. 'Invocation of the method' covers the case of recursion as well as the case of multi-threading.

On the other hand Global Variable is shared.

Yes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top