如何同步共享变量使这个程序安全?
How to synchronize the shared variables to make this program safe?
我刚刚读了 Java 并发实践这本书,它显示了一个不安全的程序:
public class NoVisibility {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread {
public void run() {
while (!ready) <=== synchronized ?
Thread.yield();
System.out.println(number);
}
}
public static void main(String[] args) {
new ReaderThread().start();
number = 42; <=== synchronized ?
ready = true; <=== synchronized ?
}
}
书中写道:
Synchronization also has another significant, and subtle, aspect: memory visibility. We want not only to prevent one thread from modifying the state of an object when another is using it, but also to ensure that when a thread modifies the state of an object, other threads can actually see the changes that were made. But without synchronization, this may not happen.
所以我明白即使没有并发写入,线程之间共享的数据,比如一个线程写入另一个线程读取,也需要同步以便写入线程发布到读取线。写入线程可以启动另一个线程,该线程将在启动读取线程后循环读取写入线程写入的数据。数据可以共享,也可以不共享。如果数据是多个变量,则可能会共享某些变量而不会共享其他变量,并且共享顺序可能会有所不同。线程之间共享的所有数据都应该同步。
如果下面的程序没有使用 synchronized 块,那么 reader 线程可能看不到 ready true,或者在看到它的数字集后它可能会看到它。未同步的数据对于线程来说将变得陈旧。为避免数据过时,必须在写访问期间和读访问期间对其进行同步。仅同步写访问不会防止数据过时。
我想知道如何使用同步语句使这个示例程序安全。
这将同步变量的读取和写入,因此它们将是可见的,它使用相同的锁(在 FixedVisibility class 上)来访问和更改静态变量。
public class FixedVisibility {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread {
public void run() {
while (!getReady())
Thread.yield();
System.out.println(getNumber());
}
}
public static synchronized boolean getReady() {
return FixedVisibility.ready;
}
public static synchronized void setReady(boolean ready) {
FixedVisibility.ready = ready;
}
public static synchronized int getNumber() {
return FixedVisibility.number;
}
public static synchronized void setNumber(int number) {
FixedVisibility.number = number;
}
public static void main(String[] args) {
new ReaderThread().start();
FixedVisibility.setNumber(42);
FixedVisibility.setReady(true);
}
}
我刚刚读了 Java 并发实践这本书,它显示了一个不安全的程序:
public class NoVisibility {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread {
public void run() {
while (!ready) <=== synchronized ?
Thread.yield();
System.out.println(number);
}
}
public static void main(String[] args) {
new ReaderThread().start();
number = 42; <=== synchronized ?
ready = true; <=== synchronized ?
}
}
书中写道:
Synchronization also has another significant, and subtle, aspect: memory visibility. We want not only to prevent one thread from modifying the state of an object when another is using it, but also to ensure that when a thread modifies the state of an object, other threads can actually see the changes that were made. But without synchronization, this may not happen.
所以我明白即使没有并发写入,线程之间共享的数据,比如一个线程写入另一个线程读取,也需要同步以便写入线程发布到读取线。写入线程可以启动另一个线程,该线程将在启动读取线程后循环读取写入线程写入的数据。数据可以共享,也可以不共享。如果数据是多个变量,则可能会共享某些变量而不会共享其他变量,并且共享顺序可能会有所不同。线程之间共享的所有数据都应该同步。 如果下面的程序没有使用 synchronized 块,那么 reader 线程可能看不到 ready true,或者在看到它的数字集后它可能会看到它。未同步的数据对于线程来说将变得陈旧。为避免数据过时,必须在写访问期间和读访问期间对其进行同步。仅同步写访问不会防止数据过时。
我想知道如何使用同步语句使这个示例程序安全。
这将同步变量的读取和写入,因此它们将是可见的,它使用相同的锁(在 FixedVisibility class 上)来访问和更改静态变量。
public class FixedVisibility {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread {
public void run() {
while (!getReady())
Thread.yield();
System.out.println(getNumber());
}
}
public static synchronized boolean getReady() {
return FixedVisibility.ready;
}
public static synchronized void setReady(boolean ready) {
FixedVisibility.ready = ready;
}
public static synchronized int getNumber() {
return FixedVisibility.number;
}
public static synchronized void setNumber(int number) {
FixedVisibility.number = number;
}
public static void main(String[] args) {
new ReaderThread().start();
FixedVisibility.setNumber(42);
FixedVisibility.setReady(true);
}
}