Java并发_volatile实现可见性但不保证原子性
来源:互联网 发布:谈谈对网络借贷的认识 编辑:程序博客网 时间:2024/05/17 00:56
读后感
- 介绍了volatile实现可见性的基本原理
- 介绍了volatile不能实现原子性的示例,volatile复合操作不能实现原子性,读取值后在自增前改值可能被其它线程读取并修改,自增后刷新值可能会覆盖其它线程修改后的值
- 介绍了实现原子性的三种方法及示例
- synchronized 修饰对象
- ReentrantLock 使用lock()、unlock()加锁解锁,比synchronized功能更多,JDK6后性能和synchronized差不多
- AtomicInteger 使用乐观锁
- synchronized 修饰对象
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();
- }
- }
阅读全文
0 0
- Java并发_volatile实现可见性但不保证原子性
- Java是怎么保证原子性,可见性
- 为什么volatile不能保证原子性而Atomic可以(valatile只保证可见性,不保证原子性)
- 保证有序性、原子性、可见性
- 【并发】java并发之可见性与原子性
- volatile 可以保证可见性,但不能保证原子性。某种意义上是线程不安全的
- java并发之原子性与可见性(一)
- Java并发编程1-原子性和可见性
- java并发之原子性与可见性
- java并发之原子性、可见性、有序性
- Java并发编程--原子性和可见性
- java并发之原子性与可见性
- java并发之原子性与可见性(一)
- java并发之原子性与可见性
- java并发之原子性与可见性
- java并发之原子性与可见性(一)
- java并发特性: 原子性、有序性、可见性
- java并发-原子性和可见性(7)
- 配置数据库连接池时,initialSize属性是什么含义
- 安卓手机使用NotificationManager弹出消息框,在上拉工具栏中
- Alternative Thinking CodeForces
- 流、文件拷贝、序列化、随机数、DecimalForamt、Calendar、SimpleDateFormat
- jvm系列(二):JVM内存结构
- Java并发_volatile实现可见性但不保证原子性
- 多线程概念
- Go安装各种第三方库,包命令
- sql 优化
- 正则表达式(括号)、[中括号]、{大括号}的区别小结
- 暑期集训之稳定排序
- 前m大的数
- 设计模式——抽象工厂模式
- 数组Array的方法