在多线程编程时会涉及到共享数据的问题,以下是个人学习的一个小例子。
我们希望程序在一秒后结束,然而第一种却永远不会停止运行。
import java.math.BigDecimal;
import java.util.concurrent.TimeUnit;
public class StopThread {
// private static boolean stopRequested ;
// public static void main(String[] args) throws InterruptedException {
// Thread backgroundThread=new Thread(new Runnable() {
//
// @Override
// public void run() {
// int i=0;
// while(!stopRequested){
// i++;
// }
// }
// });
//
// backgroundThread.start();
// TimeUnit.SECONDS.sleep(1);//永远不会终止,没有同步,不能保证后台线程何时"看到"主线程对stopRequested值的修改
// stopRequested=true;
// }
/****************synchronized**********************/
// private static synchronized void requestStop(){
// stopRequested=true;
// }
//
// private static synchronized boolean stopRequested(){
// return stopRequested;
// }
// public static void main(String[] args) throws InterruptedException {
// Thread backgroundThread=new Thread(new Runnable() {
//
// @Override
// public void run() {
// int i=0;
// while(!stopRequested()){
// i++;
// }
// }
// });
//
// backgroundThread.start();
// TimeUnit.SECONDS.sleep(1);//ok
// requestStop();
// }
/********************volatile*******************/
private static volatile boolean stopRequested ;//可以保证任何一个线程在读取改域的时候都将看到最近刚被写入的值
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread=new Thread(new Runnable() {
@Override
public void run() {
int i=0;
while(!stopRequested){
i++;
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);//ok
stopRequested=true;
}
}
总结:volatile关键字虽然比synchronized要好用,但是volatile要谨慎使用,因为可能会导致安全性失败。
最佳办法是不共享可变数据,要么共享不可变的数据,要么压根不共享。