I tried to synchronize the getters with adding synchronized
to the methods but i have always John Odd
and Jane Doe
. Any suggestion how can i synchronize the two Strings in that case ?
this is my code :
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();
}
}
The culprit is in your printing thread:
new Thread(() -> {
for (;;) {
System.out.println(board.getFirstName() + ' ' + board.getLastName());
}
}).start();
There is a chance that the internal state of board
has changed
just in between board.getFirstName()
and board.getLastName()
.
You could fix this issue in 2 ways.
Either by putting a synchronized(board) { ... }
around it
new Thread(() -> {
for (;;) {
synchronized (board) {
System.out.println(board.getFirstName() + ' ' + board.getLastName());
}
}
}).start();
or by using board.toString()
instead, which you did already synchronize properly.
new Thread(() -> {
for (;;) {
System.out.println(board.toString());
}
}).start();