zoukankan      html  css  js  c++  java
  • volatile关键字

    先看下面的代码:

    public class RunThread extends Thread{
    
        private boolean isRunning = true;
        
        private void setRunning(boolean isRunning){
            this.isRunning = isRunning;
        }
        
        public void run(){
            System.out.println("进入run方法..");
            while(isRunning == true){
                //..
            }
            System.out.println("线程停止");
        }
        
        public static void main(String[] args) throws InterruptedException {
            RunThread rt = new RunThread();
            rt.start();
            Thread.sleep(1000);
            rt.setRunning(false);
            System.out.println("isRunning的值已经被设置了false");
        }
    }

     执行代码,会发现这个程序一直会运行,而不会停止。

    因为在主线程中创建了rt对象,并且调用了run方法,启动了另一个线程,这个线程会复制isRunnning变量的副本到工作内存空间。

    所以当主线程对rt对象的属性isRunning做了更改时,对其他线程而言是无效的,因为其他的线程都有自己的副本,读取的也是副本中的内容。

    改变上述状况的方法是使用volatile关键字,isRunning属性要使用volatile关键字进行修饰。

    volatile不具备synchronized关键字的原子性(同步)

    /**
     * volatile关键字不具备synchronized关键字的原子性(同步)
     *
     */
    public class VolatileNoAtomic extends Thread{
        //private static volatile int count;
        private static AtomicInteger count = new AtomicInteger(0);
        private static void addCount(){
            for (int i = 0; i < 1000; i++) {
                //count++ ;
                count.incrementAndGet();
            }
            System.out.println(count);
        }
        
        public void run(){
            addCount();
        }
        
        public static void main(String[] args) {
            
            VolatileNoAtomic[] arr = new VolatileNoAtomic[100];
            for (int i = 0; i < 10; i++) {
                arr[i] = new VolatileNoAtomic();
            }
            
            for (int i = 0; i < 10; i++) {
                arr[i].start();
            }
        }
    }

    AtomicInteger的方法是原子性的,但是在一个方法里多个方法不是原子的

    public class AtomicUse {
    
        private static AtomicInteger count = new AtomicInteger(0);
        
        //多个addAndGet在一个方法内是非原子性的,需要加synchronized进行修饰,保证4个addAndGet整体原子性
        /**synchronized*/
        public synchronized int multiAdd(){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count.addAndGet(1);
                count.addAndGet(2);
                count.addAndGet(3);
                count.addAndGet(4); //+10
                return count.get();
        }
        
        
        public static void main(String[] args) {
            
            final AtomicUse au = new AtomicUse();
    
            List<Thread> ts = new ArrayList<Thread>();
            for (int i = 0; i < 100; i++) {
                ts.add(new Thread(new Runnable() {
                    public void run() {
                        System.out.println(au.multiAdd());
                    }
                }));
            }
    
            for(Thread t : ts){
                t.start();
            }
        }
    }
  • 相关阅读:
    Map1: iOS开发中定位和地图介绍
    GCD11: 创建计时器
    GCD10: 用GCD构建自己的分派队列
    GCD9: 用GCD将任务分组
    GCD8: 在GCD上让一个任务最多执行一次
    GCD7: 利用GCD延时后执行任务
    GCD6: 在GCD上异步执行非UI相关任务
    GCD5: 用GCD同步执行非UI相关的任务
    回文数
    字符串置换
  • 原文地址:https://www.cnblogs.com/dongdone/p/5712104.html
Copyright © 2011-2022 走看看