原子性Atomicity

简单来说就是指不能被中断的一次性操作。

在JAVA中,除了long 和double的基本类型的读和写都是原子操作。这里要注意,long 和double是64位的,他们的操作被分割为两个32位操作,因此对long 和double的读和写不是原子操作。

非原子操作在多线程环境中是会出问题的,不能达到预期。

例如写一个函数,每次都返回某个变量+1,想要实现不同的线程调用它的时候都能得到不同的值,这个是做不到的。

因此在多线程中,要使用同步机制,来确保执行某个非原子操作时候对资源进行锁定,从而实现预期的效果。

Volality

原子操作在多线程中是否能达到预期?

答案是否定的,因为现在的CPU都是多核的,每个核心都会有寄存器或者缓存,某个task对某个值进行原子性操作,但此时可能另一个task运行在另一个核中,并不能识别到前面task的操作,因此尽管操作是原子性的,但不同task仍可能视角不一致。这就是Volality。翻译成 挥发性 或者 波动性

如果使用同步机制,是可以确保不发生这种情况的。

如果不用同步机制,JAVA提供了volatile修饰符,它可以保证某个field写入时候,所有的读操作都能识别到。也就是说写入时候会强制写入主内存,并迫使所有的读都从主内存中读取。

因此这里可以看出 原子性和波动性是两个不同的概念。在单线程中是不需要用volatile的。

如果不用同步机制,那么当某field依赖它之前的值时候,volatile是不生效的。(因为这个操作是非原子性操作,不能达到预期)

volatile使用的场景通常是某个类只有一个可变的属性。

看以下例子:

public class AtomicityTest implements Runnable{private int i = 0;//加 volatile 后程序无影响public int getValue(){return i;}private synchronized void evenIncrement(){i++;i++;}@Overridepublic void run() {while(true){evenIncrement();}}public static void main(String[] args) {ExecutorService exec = Executors.newCachedThreadPool();AtomicityTest at = new AtomicityTest();exec.execute(at);while(true){int val = at.getValue();if(val % 2 !=0){System.out.print(val);System.exit(0);}}}
}

i 每次都加2,希望实现i都是偶数,运行后会发现可以读到i是奇数的情况。这里即便用了volatile来修饰,而且对写的方法也加了同步机制,但仍不能达到预期。

解决办法是,对get 读的方法也使用同步机制。

原子类

JAVA SE5 提供了原子类,用于提供原子操作,有AtomicInteger AtomicLong AtomicReference等

提供一些原子方法,我们用AtomicInteger 改造上面代码

public class AtomicIntTest implements Runnable{private volatile AtomicInteger i = new AtomicInteger(0);public int getValue(){return i.get();}private void evenIncrement(){i.addAndGet(2);}@Overridepublic void run() {while(true){evenIncrement();}}public static void main(String[] args) {ExecutorService exec = Executors.newCachedThreadPool();AtomicIntTest at = new AtomicIntTest();exec.execute(at);while(true){int val = at.getValue();if(val % 2 !=0){System.out.print(val);System.exit(0);}}}
}

可见,通过使用原子类,不使用同步机制也可以实现预期功能。

总之,可以尽量使用原子类,在不能用原子类的时候使用同步机制是可以实现预期功能的,如果你的知识足够丰富,可以使用volatile尝试去进行优化,但它只适用于少量特殊场景。

JAVA 原子性和波动性总结 Atomicity and Volality相关推荐

  1. java 原子性int_JAVA原子性操作

    java 原子性操作 Java中的原子操作包括: 1)除long和double之外的基本类型的赋值操作 2)所有引用reference的赋值操作 3)java.concurrent.Atomic.* ...

  2. 【java】Java 原子性、有序性与Happens-Before

    文章目录 1.概述 2.产生并发Bug的源头 3.线程切换带来的原子性问题 三.编译优化带来的有序性问题# 四.Java内存模型# 五.Happens-Before规则 5.1 规则1:程序的顺序性规 ...

  3. java 原子性加法_Java多線程之原子性 volatile、atomicInteger測試

    一.補充概念 1.什么是線程安全性? <Java Concurrency in Practice>中有提到:當多個線程訪問某個類時,這個類始終都能表現出正確的行為,那么就稱這個類是線程安全 ...

  4. java原子性是什么,java 原子性 可见性 有序性

    原子性 原子性是指一个操作或多个操作要么全部执行完成且执行过程不被中断,要么就不执行. 如向变量x赋值操作 x = 10 是原子性的,就不会出现赋值操作进行到一半(x的低16位赋值成功,高16位没有赋 ...

  5. Parallel programming constructs in Java;并行程序;Atomicity

    文章目录 1 Atomicity 2 Atomic Statements in Java a.Atomic Types b.Non-blocking Algorithms c.Locks d. Cou ...

  6. java原子性是什么_中级Java应该清楚的概念:原子性、可见性、有序性是什么?...

    原子性.可见性.有序性是多线程编程中最重要的几个知识点,由于多线程情况复杂,如何让每个线程能看到正确的结果,这是非常重要的,下面和千锋广州小编一起来看看吧! ​ 原子性 原子性是指一个线程的操作是不能 ...

  7. java原子性和原子操作理解

    原子性:即一个操作或者多个操作 要么全部执行 并且执行的过程不会被任何因素打断,要么就都不执行. 举个例子:假如为一个32位的变量赋值过程不具备原子性的话,会发生什么后果? int i=9: 假若一个 ...

  8. 程序员交流平台_Java虚拟机所管理的内存到底有哪些?Java程序员必看栏目(上)...

    Java虚拟机所管理的内存将会包括以下几个运行时数据区域: 1,程序计数器Program Counter Register 一块较小的内存空间,非所有线程共享的区域,每个程序计数器,都会记录当前线程执 ...

  9. JAVA知识梳理(日常整理)

    Java基础 JAVA 中的几种数据类型是什么,各自占用多少字节. String 类能被继承吗,为什么. 不能被继承,因为String类有final修饰符,而final修饰的类是不能被继承的. *很多 ...

最新文章

  1. DHCP服务器的配置详细说明
  2. 成功解决Instructions for updating:  Use `tf.global_variables_initializer` instead.
  3. ActiveReports报表控件教程之单元格合并
  4. 125 Valid Palindrome
  5. 佳能80d有人脸识别吗_2020单反/微单相机推荐,单反和微单(无反)选购攻略,佳能、尼康、索尼、富士、松下相机...
  6. AI发票扫描识别sdk软件接口
  7. linux富文本软件,CherryTree(技术人员专用富文本笔记软件)
  8. 连续多帧图像光流对齐和光流运动检测
  9. Linux必会的rpm命令安装软件
  10. java chr()_chr码值对应列表大全
  11. Adobe帝国的产品线
  12. bat脚本中pause的作用
  13. javaEye上对于南京软件公司的讨论
  14. 解决(‘You must install pydot (`pip install pydot`) and install graphviz (see...) ‘, ‘for plot_model..
  15. 树莓派 USB麦克风 录音
  16. 程序员成功之路 ——The road ahead for programmer(演讲稿)(转)
  17. Linux游戏 0 A.D安装及汉化
  18. ThinkPHP,是为了简化企业级应用开发和敏捷WEB应用开发而诞生的开源轻量级PHP框架。
  19. 1.16 be going to and will
  20. realtek没有禁用前面板_教你win7系统realtek禁用前面板插孔检测的具体步骤

热门文章

  1. 图形API学习工程(28):实现基于Cook-Torrance与GGX的PBR渲染
  2. JS刷新页面的几种方法
  3. a16z:如何改善 Web3 治理?
  4. 交流等效电路,电源相当于是接地?为啥?
  5. 软考 纸质和电子书_重新思考纸质原型,我如何看待它作为游乐场和实验
  6. Linux drm设置默认分辨率,Wayland如何设置自定义分辨率
  7. Seq2Seq model个人小记
  8. flume变量加载存放实例
  9. Splunk 打开HTTPS
  10. 组件化开发和模块化开发