class="java" name="code">
public class NoVisibility {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread{
public void run(){
while(!ready){
Thread.yield();
System.out.println(number);
}
}//end run()
}//end Class ReaderThread
public static void main(String[] args){
new ReaderThread().start();
number = 42;
ready = true;
}
}
NoVisibility可能不会打印任何值,因为读
线程可能永远看不到ready的值。一种更奇怪的现象是,NoVisibility可能会输出0,因为读线程可能看到了写入的ready的值,但是却没有看到之后写入的number的值。只要有数据在多个线程之间共享,就应该使用正确的
同步。
public class MutableInteger {
private int value;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
MutableInteger不是
线程安全的,因为get和set都是在没有同步的情况下访问value的。
public class SynchronizedInteger {
@GuardedBy("this")private int value;
public synchronized int getValue() {
return value;
}
public synchronized void setValue(int value) {
this.value = value;
}
}
SynchronizedInteger中,通过对get和set方法进行同步,可以使MutableInteger成为一个线程安全类。仅对set方法进行同步是不够的。另外,在多线程程序中使用共享且可变的long和double等类型的变量也是不安全的,可以使用volatile来声明,或者用锁保护起来(加锁机制既可以确保可见性又可以确保原子性,而volatile变量只嗯呢该确保可见性)。