atomicity and volatility 代替synchronized 对象锁 的另一种方法(原子操作+可见性)
来源:互联网 发布:淘宝退款怎么退一部分 编辑:程序博客网 时间:2024/05/20 06:50
参考文章:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile
https://www.ibm.com/developerworks/library/j-jtp06197/index.html
https://tutorials.jenkov.com/java-concurrency/volatile.html
1、atomicity(原子操作):一个操作不中断,一直执行完
对成员变量进行操作。
volatile:就是在原子操作下,保证变量的visible。
2、按照:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile
编译和运行时:
1>禁止分配它们到寄存器(registers),保证一个线程写后能马上更新到内存,所有线程都能看见,
2>必须保证volatile变量读之前缓冲区(cpu cache)无效,哪么线程只能在内存读。
class VolatileExample { int x = 0; volatile boolean v = false; public void writer() { x = 42; v = true; } public void reader() { if (v == true) { //uses x - guaranteed to see 42. } }}
1>如果v不是volatile变量,哪么reader()读操作,当v==true,有可能读到x=0。原因:有可能编译器重新排序 v=true,x=42,哪么读出的是未改变的值。
所以:编译器看见有volatile变量存在的地方,有cpu缓存,但是读时不让去缓冲读,直接从内存读,不重新排序。
一、功能介绍
1、atomicity :原子操作,也叫lock-free 无锁,即不需要锁操作。
优点:操作不能被thread 调度者中断,一气呵成,比如:正在高考数学,考完才出来吧!
atomicity :对应单cpu ,在多cpu用 visibility代替。
2、比较
synchronized:不能保证共享变量前的所有变量数据(非共享数据)一定会存入内存。如果是共享数据,哪么感觉两个线程基本上会看见新值。
因为这syn对象锁保证只有单独一个线程读数据后,保存到内存,下一个线程才能读,这是syn对象锁的基本功能。atomicity,volatile:
编译器或jvm不能重新排序volatil 指令的执行顺序。 特殊情况有可能如下:
一个synchronized 线程改变成员变量值后
1》首先应该写入到缓冲中,如果当前干活线程改变值后,值存放在缓中,未向内存写。
2》这时手动删除本window7的缓存,
3》下一个线程执行的话,去内存取,还是以前的值,所以刚刚改的值根本未入内存
感觉只有这种情况下才会出错,一般应该没问题。1>一个线程写入变量后,马上入内存。
2>多个线程读,直接去内存读,所以这种情况数据不存在一致性问题。
但是,如果一个线程写入变量到cache后,未入内存,刚好另一个线程从内存读,又出现一致性问题了。
目前默认原子操作的变量:primtive types(int,char,byte):原子操作,读、写只需要一条指令即可。
1》返回值 return i;这是一个原子操作。
3、 volatility:对syn对象锁的补充。
a long or double:是64位,一次读,非原子操作,需要分成两个32位来操作,对应两条指令,两条指令中间可以插入其它指令。
(1) 设置成员变量:非volatility
当对一个线程对成员变量进行的an atomic 操作时,就我一个干活线程用,别的干活线程不用,哪么也不需要刷新main memory了(主要目的让别的线程看见新改的值)
(2)设置成员变量:volatility (有波动的意思)
1>实时更新数据
多个干活线程访问同一个成员变量时,必须设置成volatility ,当一个线程改了成员变量值,哪么所有用到这个成员变量的干活线程必须能看见新改的值。
2>volatility 可以让一个long 变量成为原子操作?未测试
本来一个64位的 long是非原子操作。
二、例子: 一看,感觉下面两个方法对成员变量i是原子操作
但是指令“get” 和 "put" 之间,另一个对象也可以修改成员变量的值,所以下面操作非原子。
Atomicity 类,可以new Atomicity(),生成多个对象,并且多个对象都可以操作f1(),f2()方法,有可能存在先执行,同时执行等待的可能。
package concurrency;public class Atomicity {
int i;
void f1() {
i++;
}
void f2() {
i += 3;
}
}反编译:
void f1();
Code:
0: aload_0
1: dup
2: getfield #2; //取得成员变量i
5: iconst_1
6: iadd
7: putfield #2; //保存成员变量i
10: return
void f2();
Code:
0: aload_0
1: dup
2: getfield #2; //Field i:I
5: iconst_3
6: iadd
7: putfield #2; //Field i:I
10: return
三、不要盲目使用原子的思想
下面例子本想取一个偶数值,但是由于getValue 以为是原子操作,没有设置对象锁。
因此当evenIncrement 执行到一个i++后(奇数)------getValue 取值,出现错误。
1、成员变量 i
2、方法getValue(只有返回值),是一个原子操作
3、方法 evenIncrement 带有对象锁 自增1,两次,
4、干活线程AtomicityTest,
package concurrency;
import java.util.concurrent.*;
public class AtomicityTest implements Runnable {
private int i = 0;
public int getValue() {
return i;
}
private synchronized void evenIncrement() {
i++;
i++;
}
public void run() {
System.out.println("run 开始!");
while (true)
evenIncrement();
}
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
AtomicityTest at = new AtomicityTest();
exec.execute(at);
System.out.println("main!");
while (true) {
System.out.println("main 循环开始!");
int val = at.getValue();
System.out.println("val ="+val);
if (val % 2 != 0) {
System.out.println(val);
System.exit(0);
}
}
}
}
参考文章:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile
- atomicity and volatility 代替synchronized 对象锁 的另一种方法(原子操作+可见性)
- Atomicity(原子性),visibility(可被观察性),volatility(挥发性)
- Atomicity(原子性),visibility(可被观察性),volatility(挥发性)
- 原子性(atomicity)
- JAVA 原子性和波动性总结 Atomicity and Volality
- 知识库--Ensure Atomicity 原子性保证(117)
- Java多线程总结(5)— 原子性、可见性、有序性和并发库的原子性操作
- 内存可见性和原子性:Synchronized和Volatile的比较
- Java多线程之内存可见性和原子性:Synchronized和Volatile的比较
- 内存可见性和原子性:Synchronized和Volatile的比较
- Volatile和Synchronized对可见性和原子性的支持
- 内存可见性和原子性:Synchronized和Volatile的比较
- 原子性与可见性 volatile与synchronized关键字
- Synchronized的内存可见性
- 事务的原子性、一致性、隔离性、持久性(atomicity,consistency,isolation,durability)
- 对 原子性,可见性的理解
- Java的原子性&&可见性&&有序性
- 原子性和可见性的理解
- Ajax请求到action,action返回整个页面的方式
- MyEclipse 2017 ci6 安装反编译插件(本人自己摸索的方法,亲测可行)
- 容器与服务器的区别与联系:Servlet容器 WEB容器 Java EE容器 应用服务器 WEB服务器 Java EE服务器
- Spring JdbcDaoSupport Tutorial
- CentOS7配置nginx php php-fpm mariadb phpmyadmin(yum安装)
- atomicity and volatility 代替synchronized 对象锁 的另一种方法(原子操作+可见性)
- PowerShell的学习笔记(4)---- 如何在使用Enter-PSSession的时候解决TrustedHosts list的问题?
- “王者荣耀”与大数据平台的产品化思想
- MySQL复制原理
- WWDC2017:ARKit初探
- C# Round源码
- Linux下的文件流和文件描述符
- charlesproxy 网络抓包工具
- Lynx 简明使用指南