关键字volatile的作用是强制从公共堆栈中取得变量的值,而不是从线程私有数据栈中取得变量的值。
 1.先做一个实验:
     * 源码:   
         public class RunThread extends Thread{
         private boolean isRunning=true;
         public boolean isRunning() {
             return isRunning;
         }
         public void setRunning(boolean running) {
             isRunning = running;
         }
         @Override
         public void run() {
             System.out.println("进入run了");
             while(isRunning == true){
             }
             System.out.println("线程被停止了!");
         }
     }
         public class Run {
         public static void main(String[] args){
             RunThread thread=new RunThread();
             thread.start();
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             thread.setRunning(false);
             System.out.println("已经赋值为false");
         }
     }
         运行该代码,发现根本不会停止的,什么原因呢?
         在启动RunThread.java线程是,变量isRunning=true;存在与公共堆栈及线程的私有堆栈中。
         为了运行的效率,线程一直在私有堆栈中取得isRunning的值是true,而更新的却是公共堆栈中
         的isRunning变量值false.所以一直就是死循环的状态。
         改成:
         volatile private boolean isRunning=true;
         就可以了,volatile关键字的作用就是当线程访问isRunning这个变量是,强制性从公共堆栈中进行取值。
 2. 关键字synchronized和volatile进行比较:
     * 关键字volatile是线程同步的轻量级实现,所以volatile性能肯定比 synchronized要好,并且 volatile只能
         修饰于变量,而 synchronized可以修饰方法,以及代码块。
     * 多线程访问volatile不会发生阻塞,而 synchronized会发生阻塞
     * volatile能保证数据的可见性,但不能保证原子性;而 synchronized可以保证原子性,也可以间接保证可见性,
         因为它会将私有内存和公有内存中的数据做同步、
     * 关键字volatile解决的是变量在多个线程之间的可见性;而synchronized关键字解决的是多个线程之间访问资源的同步性。
 3. volatile 非原子的特性
     * 案例说明volatile不具有原子性和同步性
     eg
         public class MyThread extends Thread {
         volatile public static int count;
         private static void addCount() {
             count++;
             System.out.println("count=" + count);
         }
         @Override
         public void run() {
             addCount();
         }
     }
         public class Run {
         public static void main(String[] args){
             MyThread[] myThreads=new MyThread[100];
             for(int i=0;i<100;i++){
                 myThreads[i]=new MyThread();
             }
             for(int i=0;i<100;i++){
                 myThreads[i].start();
             }
         }
     }
         运行后发现,好多变量出现了好多次哦,这是因为i++不是原子性的,分为三步:
             * 从内存中取出i的值
             * 计算i的值
             * 将i的值写到内存中
 3. synchronized代码块有volatile同步的功能
     * 关键字synchronized可以使多个线程访问同一个资源具有同步性,而且它还具有将线程工作内存中的
         私有变量与公共内存中的变量同步的功能
         eg:
         public class Service {
         private boolean isContinueRun=true;
         public void runMethod(){
             while(isContinueRun==true){
             }
             System.out.println("停下来了!");
         }
         public void stopMethod(){
             isContinueRun=false;
         }
     }
         public class ThreadA extends Thread{
         private Service service;
         public ThreadA(Service service){
             super();
             this.service=service;
         }
         @Override
         public void run() {
             service.runMethod();
         }
     }
         public class ThreadB extends Thread {
         private Service service;
         public ThreadB(Service service){
             super();
             this.service=service;
         }
         @Override
         public void run() {
             service.stopMethod();
         }
     }
         public class Run {
         public static void main(String[] args){
             Service service=new Service();
             ThreadA a=new ThreadA(service);
             a.start();
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             ThreadB b=new ThreadB(service);
             b.start();
             System.out.println("已经发起停止的命令了!");
         }
     }
     该代码并不能停止,具体前面说了,没有可见性,前面是用volatile实现的,现在用synchronized
     Service代码做如下更改:
         public class Service {
         private boolean isContinueRun=true;
         public void runMethod(){
             String anyString=new String();
             while(isContinueRun==true){
                 synchronized (anyString){
                     
                 }
             }
             System.out.println("停下来了!");
         }
         public void stopMethod(){
             isContinueRun=false;
         }
     }
         现在可以了,s关键字synchronized可以保证在同一时刻,只有一个线程可以执行某一个方法或某一个代码块。
         它包含两个特征:互斥性和可见性。同步synchronized不仅可以解决一个线程看到对象处于不一致的状态,还
         可以保证进入同步方法或者同步代码块的每个线程,都看到由同一个锁保护之前所有的修改效果。(书上原话= =)
         在我的理解,如果锁加在isContinueRun上是可以理解的,为了同步,肯定会强制用公共堆栈,但是加在anyString上= =,
         anyString被强制公共堆栈并没有什么卵用= =,在我的理解是,加了synchronized关键词,在未执行到指定代码之前,
         虚拟机并不知道锁在哪个对象上,为了让锁的对象永远保持一个,保证同步,只要类中出现synchronized关键字,就把
         所有对象的存取指定在公共堆栈。(个人看法)。
                










