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

我已经开始深入学习线程,并在尝试理解我编写以下代码的概念的同时,我不确定代码的输出。以下是我编写的代码,


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 块

线程的运行方法

线程的运行方法。

请帮助我理解流程。


皈依舞
浏览 172回答 2
2回答

函数式编程

将您的方法声明为public synchronized Person getPerson()意味着它使用包含UnsafeCheck实例(即this)作为监视器来同步访问。当您创建三个不同的UnsafeCheck实例时,每个实例都有自己的锁,并且代码不会按照您的预期执行。和public static synchronized Person getPerson()使用的监视器对于所有实例都是相同的,即UnsafeCheck.class,您会获得正确的static Person变量同步。有关synchronized方法的更多信息,请查看 Oracle 的教程:同步方法。

Cats萌萌

好的,现在我知道你在做什么了,标题有误导性。监视器的同步关键字以对象方式锁定它,因此只有一个线程可以进入方法 PER Object。你可以做两件事来让它广泛应用:1.使 getPerson 方法静态(它将在应用程序范围内同步)2.使用同步块,允许您选择同步对象(通常“this”用于对象同步,“UnsafeCheck.class”用于应用程序范围)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java