我已经开始深入学习线程,并试图理解我编写的以下代码的概念,但是我不确定代码的输出。以下是我编写的代码,
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();
}
}
输出:
thread's run method Inside if block thread's run method Inside if block thread's run method Inside if block
如果我们观察到线程uc所做的输出更改未反映在线程uc1中,这就是为什么每个线程控制都转到if块的原因。 我希望当uc1执行run方法时人员引用会被初始化,但是uc1线程的人员仍然为空。
我进行的另一项有趣的观察是,如果将getPerson()方法设置为静态,则会得到预期的输出。以下是getPerson()方法为静态时的输出。
输出:
thread's run method Inside if block thread's run method thread's run method.
请帮助我理解流程。
答案 0 :(得分:1)
将您的方法声明为
public synchronized Person getPerson()
表示它正在使用包含的UnsafeCheck
实例(即this
)作为监视器来同步访问。在创建三个不同的UnsafeCheck
实例时,它们中的每个实例都有其自己的锁,并且代码无法执行您期望的操作。
使用
public static synchronized Person getPerson()
在所有实例(即UnsafeCheck.class
)上使用的监视器都是相同的,并且您为static
Person
变量获得了正确的同步。
有关synchronized
方法的更多信息,请查看Oracle教程:Synchronized Methods。
答案 1 :(得分:0)
好吧,现在我知道您在做什么,标题令人误解。监视器的synced关键字以对象为单位对其进行锁定,因此只有一个线程可以进入方法PER Object。
您可以做两件事来使它在整个应用程序范围内:
1.make getPerson方法为静态(它将在整个应用程序范围内同步)
2。使用允许您拾取同步对象的同步块(通常是“ this”用于对象同步,而“ UnsafeCheck.class”则用于整个应用程序)