为了账号安全,请及时绑定邮箱和手机立即绑定

一个线程所做的更改不会反映在另一个线程中

一个线程所做的更改不会反映在另一个线程中

皈依舞 2021-09-15 14:54:21
我已经开始深入学习线程,并在尝试理解我编写以下代码的概念的同时,我不确定代码的输出。以下是我编写的代码,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();            }   }输出:线程的运行方法内部 if 块线程的运行方法内部 if 块线程的运行方法内部 if 块如果我们观察到线程 uc 所做的输出更改并没有反映在线程 uc1 中,这就是为什么每个线程控制都转到 if 块的原因。我期望在 uc1 执行 run 方法时初始化 person 引用,但是对于 uc1 线程来说 person 仍然为空。我所做的一个更有趣的观察是,如果我将 getPerson() 方法设为静态,我将按预期获得输出。以下是 getPerson() 方法为静态时的输出。输出:线程的运行方法内部 if 块线程的运行方法线程的运行方法。请帮助我理解流程。
查看完整描述

2 回答

?
函数式编程

TA贡献1807条经验 获得超9个赞

将您的方法声明为

public synchronized Person getPerson()

意味着它使用包含UnsafeCheck实例(即this)作为监视器来同步访问。当您创建三个不同的UnsafeCheck实例时,每个实例都有自己的锁,并且代码不会按照您的预期执行。

public static synchronized Person getPerson()

使用的监视器对于所有实例都是相同的,即UnsafeCheck.class,您会获得正确的static Person变量同步。

有关synchronized方法的更多信息,请查看 Oracle 的教程:同步方法


查看完整回答
反对 回复 2021-09-15
?
Cats萌萌

TA贡献1805条经验 获得超9个赞

好的,现在我知道你在做什么了,标题有误导性。监视器的同步关键字以对象方式锁定它,因此只有一个线程可以进入方法 PER Object。

你可以做两件事来让它广泛应用:

1.使 getPerson 方法静态(它将在应用程序范围内同步)

2.使用同步块,允许您选择同步对象(通常“this”用于对象同步,“UnsafeCheck.class”用于应用程序范围)


查看完整回答
反对 回复 2021-09-15
  • 2 回答
  • 0 关注
  • 171 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信