synchronized可以实现原子性,以及确保一个线程修改了某个数据的值之后,其他线程能够看到发生的变化。
如果没有同步,我们无法保证一个读线程能够及时看到其它写线程的写入的值。
public class KeJianXing {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread{
@Override
public void run() {
while (!ready){
Thread.yield();
}
System.out.println(number);
}
}
public static void main(String[] args){
new ReaderThread().start();
number=33;
ready=true;
// System.out.println(“zhixingjieshu”);
}
另一种稍弱的同步机制是 volatile,被volatile标识的变量的操作不会被重排序,同时,修改了volatile修饰的变量的值之后,在它之前的所有修改也都会同步到内存之中,变为可见。
在对象构造完成之前,就公布了对象的引用,可能会导致线程安全问题。
在对象构造过程中发布当前对象引用的方式有:
public class ThisEscape{
public ThisEscape(EventSource source){
source.registerListener{
new EventListener(){
public void onEvent(Event e){
doSomething(e,this);
}
}
}
}
}
public class ThisEscape{
public ThisEscape(EventSource source){
new Thread(()-{
doSomeThing(this);
}).start();
}
}
可以时候用一个私有的构造函数和一个公共的工厂方法来避免这种不正确 的构造过程。如下:
public class SafeListener{
private final EventListener listener;
private SafeListener(){
listener=new EventListener(){
public void onEvent(Event e){
doSomething(e);
}
}
}
public static SafeListener newInstance(EventSourcesource){
SafeListener safe=new SafeListener();
source.registerListener(safe.listener);
return safe;
}
}
关键就是把线程的启动和创建分开。