您的位置:首页 > 编程语言 > Java开发

Java并发_volatile实现可见性但不保证原子性

2017-07-23 19:55 330 查看
读后感

介绍了volatile实现可见性的基本原理
介绍了volatile不能实现原子性的示例,volatile复合操作不能实现原子性,读取值后在自增前改值可能被其它线程读取并修改,自增后刷新值可能会覆盖其它线程修改后的值
介绍了实现原子性的三种方法及示例
synchronized  修饰对象

ReentrantLock 使用lock()、unlock()加锁解锁,比synchronized功能更多,JDK6后性能和synchronized差不多

AtomicInteger  使用乐观锁

  volatile关键字:
能够保证volatile变量的可见性
不能保证volatile变量复合操作的原子性

  volatile如何实现内存可见性:

         深入来说:通过加入内存屏障和禁止重排序优化来实现的。
对volatile变量执行写操作时,会在写操作后加入一条store屏障指令
对volatile变量执行读操作时,会在读操作前加入一条load屏障指令

         通俗地讲:volatile变量在每次被线程访问时,都强迫从主内存中重读该变量的值,而当该变量发生变化时,又会强迫线程将最新的值刷新到主内存。这样任何时刻,不同的线程总能看到该变量的最新值。

 

         线程写volatile变量的过程:
改变线程工作内存中volatile变量副本的值
将改变后的副本的值从工作内存刷新到主内存

         线程读volatile变量的过程:
从主内存中读取volatile变量的最新值到线程的工作内存中
从工作内存中读取volatile变量的副本

         volatile不能保证volatile变量复合操作的原子性:

private int number = 0;  

number++; //不是原子操作  

         它分为三步:

         读取number的值

         将number的值加1

         写入最新的number的值

 

          保证number自增操作的原子性:
使用synchronized关键字
使用ReentrantLock
使用AtomicInteger

          使用synchronized关键字

import java.util.concurrent.ExecutorService;  

import java.util.concurrent.Executors;  

  

/** 

 * @author InJavaWeTrust 

 */  

public class TestSyn implements Runnable {  

  

    private int number = 0;  

  

    public int getNumber() {  

        return this.number;  

    }  

  

    public void run() {  

        increase();  

    }  

  

    public void increase() {  

        synchronized (this) {  

            this.number++;  

        }  

    }  

  

    public static void main(String[] args) {  

        ExecutorService exec = Executors.newFixedThreadPool(1000);  

        TestSyn syn = new TestSyn();  

        for (int i = 0; i < 1000; i++) {  

            exec.submit(syn);  

        }  

        System.out.println("number : " + syn.getNumber());  

        exec.shutdown();  

    }  

}  

 

          使用ReentrantLock

import java.util.concurrent.ExecutorService;  

import java.util.concurrent.Executors;  

import java.util.concurrent.locks.Lock;  

import java.util.concurrent.locks.ReentrantLock;  

/** 

 * @author InJavaWeTrust 

 */  

public class TestRee implements Runnable {  

  

    private Lock lock = new ReentrantLock();  

    private int number = 0;  

  

    public int getNumber() {  

        return this.number;  

    }  

  

    public void run() {  

        increase();  

    }  

  

    public void increase() {  

        lock.lock();  

        try {  

            this.number++;  

        } finally {  

            lock.unlock();  

        }  

    }  

  

    public static void main(String[] args) {  

        TestRee ree = new TestRee();  

        ExecutorService exec = Executors.newFixedThreadPool(1000);  

        for (int i = 0; i < 1000; i++) {  

            exec.submit(ree);  

        }  

        System.out.println("number : " + ree.getNumber());  

        exec.shutdown();  

    }  

}  

 

          使用AtomicInteger

import java.util.concurrent.ExecutorService;  

import java.util.concurrent.Executors;  

import java.util.concurrent.atomic.AtomicInteger;  

  

/** 

 * @author InJavaWeTrust 

 */  

public class TestAtomic implements Runnable {  

  

    private static AtomicInteger number = new AtomicInteger(0);  

  

    public void run() {  

        increase();  

    }  

  

    public void increase() {  

        number.getAndAdd(1);  

    }  

  

    public static void main(String[] args) {  

        TestAtomic ato = new TestAtomic();  

        ExecutorService exec = Executors.newFixedThreadPool(1000);  

        for (int i = 0; i < 1000; i++) {  

            exec.submit(ato);  

        }  

        System.out.println("number : " + number.get());  

        exec.shutdown();  

    }  

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐