Kilarapu Yethendra
Kilarapu Yethendra

Reputation: 99

Changes made by one thread are not reflected in another thread

I have started learning threads in depth and while trying to understand the concepts I wrote the following code and I am not sure about the output of the code.Following is the code I wrote,

public class UnsafeCheck extends Thread {
    private static Person person;


    // This method is not thread safe without synchronization. Make the method 
    // synchronized to make the code thread safe.
    public synchronized Person getPerson() {
        if(person == null) {
            System.out.println("Inside if block");
            person = new Person("Kilarapu Yethendra", 27);
        }
        return person;
    }

    public void run() {
        System.out.println("thread's run method");
        getPerson();
    }

    public static void main(String[] args) {
        UnsafeCheck uc = new UnsafeCheck();
        uc.start();

        UnsafeCheck uc1 = new UnsafeCheck();
        uc1.start();

        UnsafeCheck uc2 = new UnsafeCheck();
        uc2.start();        
    }   
}

Output:

thread's run method
Inside if block
thread's run method
Inside if block
thread's run method
Inside if block

If we observe the output changes made by the thread uc is not reflected in the thread uc1, which is why for each thread control is going to the if block. I have expected person reference to be initialized when the uc1 executes the run method but person is still null for uc1 thread.

One more interesting observation I made was that if I make the getPerson() method as static I am getting the output as expected. Following is the output when getPerson() method is static.

Output:

thread's run method
Inside if block
thread's run method
thread's run method.

Kindly help me understand the flow.

Upvotes: 2

Views: 800

Answers (2)

maslan
maslan

Reputation: 2178

Ok, now I know what are You up to, the title is misleading. The synchronized keyword for a monitor locks it object-wise, so only one thread can enter the method PER Object.

You can do two things to have it application wide:

1.make getPerson method static (it will be synchronized application wide)

2.Use synchronized blocks that allow You to pick up synchronization objects (usually "this" for object-wise synchronization and "UnsafeCheck.class" for application wide)

Upvotes: 0

Mick Mnemonic
Mick Mnemonic

Reputation: 7956

Declaring your method as

public synchronized Person getPerson()

means that it's synchronizing access using the containing UnsafeCheck instance (i.e. this) as the monitor. As you're creating three different UnsafeCheck instances, each of them will have their own lock and the code doesn't do what you expect it to do.

With

public static synchronized Person getPerson()

the monitor used is the same for all instances, i.e. UnsafeCheck.class, and you get correct synchronization for the static Person variable.

For more information about synchronized methods, have a look at Oracle's tutorial: Synchronized Methods.

Upvotes: 1

Related Questions