Как я могу синхронизировать геттеры без непоследовательного состояния? - PullRequest
0 голосов
/ 20 мая 2018

Я пытался синхронизировать геттеры с добавлением synchronized к методам, но у меня всегда есть John Odd и Jane Doe.Любое предложение, как я могу синхронизировать две строки в этом случае?

это мой код:

public class HonorBoard {
    private volatile String firstName;
    private volatile String lastName;


    public void set(String firstName, String lastName) {
        synchronized (this) {
            this.firstName = firstName;
            this.lastName = lastName;
        }
    }

    private synchronized String getFirstName() {
        return firstName ;
    }

    private synchronized String getLastName() {
        return lastName;
    }

    @Override
    public synchronized String toString() {
        return firstName + ' ' + lastName;
    }

    public static void main(String[] args) {
        HonorBoard board = new HonorBoard();
        new Thread(() -> {
            for (;;) {
                board.set("John", "Doe");
            }
        }).start();

        new Thread(() -> {
            for (;;) {
                board.set("Jane", "Odd");
            }
        }).start();

        new Thread(() -> {
            for (;;) {
                System.out.println(board.getFirstName() + ' ' + board.getLastName());
            }
        }).start();
    }

}

Ответы [ 2 ]

0 голосов
/ 20 мая 2018

Виновник в вашей нити печати:

new Thread(() -> {
    for (;;) {
        System.out.println(board.getFirstName() + ' ' + board.getLastName());
    }
}).start();

Существует вероятность того, что внутреннее состояние board изменилось только между board.getFirstName() и board.getLastName().

Эту проблему можно решить двумя способами.

  • Либо поместив вокруг нее synchronized(board) { ... }

    new Thread(() -> {
        for (;;) {
            synchronized (board) {
                System.out.println(board.getFirstName() + ' ' + board.getLastName());
            }
        }
    }).start();
    
  • , либо используя board.toString() вместо этого, который вы уже правильно синхронизировали.

    new Thread(() -> {
        for (;;) {
            System.out.println(board.toString());
        }
    }).start();
    
0 голосов
/ 20 мая 2018

Я не думаю, что это возможно с двумя методами получения.я бы заменил getFirstname и getLastname на getName и возвратил бы либо массив из двух элементов, либо Java-бин, который содержит и имя, и фамилию вместе.внутри этого метода получения вы будете использовать синхронизированный блок, как в своем установщике, внутри этого блока вы создаете массив или компонент.я думаю, что это должно сработать.

...