Изменения, сделанные одним потоком, не отражаются в другом потоке - PullRequest
0 голосов
/ 12 сентября 2018

Я начал углубленно изучать потоки и, пытаясь понять концепции, я написал следующий код, и я не уверен в выводе кода. Следующий код, который я написал,

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.Я ожидал, что ссылка на person будет инициализирована, когда uc1 выполняет метод run, но person по-прежнему равен null для потока uc1.

Еще одно интересное наблюдение, которое я сделал, заключалось в том, что если я сделаю метод getPerson () статическим, я будуполучить результат, как и ожидалось.Ниже приведен вывод, когда метод getPerson () является статическим.

Вывод:

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

Пожалуйста, помогите мне понять поток.

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Хорошо, теперь я знаю, чем Вы занимаетесь, название вводит в заблуждение.Ключевое слово synchronized для монитора блокирует его объектно-ориентированным образом, поэтому только один поток может ввести метод PER Object.

Вы можете сделать две вещи, чтобы иметь его в масштабе приложения:

1.make getPersonстатический метод (он будет синхронизирован во всем приложении)

2.Используйте синхронизированные блоки, которые позволяют выбирать объекты синхронизации (обычно «this» для объектной синхронизации и «UnsafeCheck.class» для всего приложения)

0 голосов
/ 12 сентября 2018

Объявление вашего метода как

public synchronized Person getPerson()

означает, что он синхронизирует доступ, используя в качестве монитора экземпляр UnsafeCheck (то есть this).Когда вы создаете три разных UnsafeCheck экземпляра, каждый из них будет иметь свою собственную блокировку, и код не будет делать то, что вы ожидаете.

С

public static synchronized Person getPerson()

используемый монитор одинаков для всех экземпляров, т. е. UnsafeCheck.class, и вы получите правильную синхронизацию для переменной static Person.

Для получения дополнительной информации о synchronized методах ознакомьтесь с Oracleучебное пособие: Синхронизированные методы .

...