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();
        }
    }
}
原文地址:https://www.cnblogs.com/dongdone/p/5712104.html