Reputation: 99
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
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
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