volatile -- 最轻量级的同步机制

特性

  1. 保证变量对所有线程的可见性 -- 即当一条线程改变了该变量的值,其他线程立刻得知
  2. 禁止了指令重排序优化

Java内存模型实现volatile

load + use 必须连续一起出现,这就保证了线程从主内存读到的值是最新的值

assign + store + write必须连续一起出现,这就保证了线程修改的值必须立刻更新到主内存

对于两个变量A和B,如果先对A执行了use或assign操作,那么就要比对B先执行read或write操作,这保证了指令不能重排序

并发不安全

虽然volatile变量的值一旦修改就能立刻得知,但是它的运算操作需要时间,在这段时间内变量的值可能被修改,因此不安全

如何保证线程安全?

只能用synchornized或者是Lock类实现同步

适用情况

  1. boolean flag情景,使用bool变量作为开关
  2. 双锁单例模式中使用volatile来保证实现唯一实例:如果没有volatile,线程1new获取实例的信息没有立刻得到更新且放开了synchronized锁,其他线程就会因为实例 == null继续new

指令重排序

普通的变量只保证需要赋值的变量能得到正确结果而不保证指令执行顺序

意义

JVM能够根据处理器的特性(CPU的多级缓存系统、多核处理器等)适当的重新排序机器指令,使机器指令更符合CPU的执行特点,最大限度的发挥机器的性能

内存屏障

重排序时不能把后面的指令重排序到内存屏障之前,通过给指令加lock实现

性能

volatile总开销比锁低,只是写操作因为插入了许多内存屏障可能会慢一点,如果volatile能满足需求就用volatile

原文地址:https://www.cnblogs.com/ming-szu/p/9462222.html

时间: 2024-11-10 12:21:53

volatile -- 最轻量级的同步机制的相关文章

java——同步机制(synchronized, volatile)

1. java的线程间通信是由java的内存模型(JMM)来控制的. JMM(java memory management) 定义了线程和主内存之间的抽象关系,一个是主内存(多线程之间来进行共享),一个是每个线程自己的私有内存 2. 为什么需要同步机制? (1) 同步机制一般发生在多线程中,当需要跨线程维护程序的正确性,当需要多个线程之间共享非final变量时,就必须使用同步机制来保证一个线程的操作对于另一个线程是可见的 (2) 同步机制保证了多个线程之间的可靠通信,保证了多个线程之间对共享变量

轻量级的同步机制——volatile语义详解(可见性保证+禁止指令重排)

1.关于volatile volatile是java语言中的关键字,用来修饰会被多线程访问的共享变量,是JVM提供的轻量级的同步机制,相比同步代码块或者重入锁有更好的性能.它主要有两重语义,一是保证多个线程对共享变量访问的可见性,二防止指令重排序. 2.语义一:内存可见性 2.1 一个例子 public class TestVolatile { public static void main(String[] args) throws InterruptedException { ThreadD

Linux 内核的同步机制,第 1 部分 + 第二部分(转)

http://blog.csdn.net/jk198310/article/details/9264721  原文地址: Linux 内核的同步机制,第 1 部分 一. 引言 在现代操作系统里,同一时间可能有多个内核执行流在执行,因此内核其实象多进程多线程编程一样也需要一些同步机制来同步各执行单元对共享数据的访问.尤其是在多处理器系统上,更需要一些同步机制来同步不同处理器上的执行单元对共享的数据的访问.在主流的Linux内核中包含了几乎所有现代的操作系统具有的同步机制,这些同步机制包括:原子操作

【总结】Java线程同步机制深刻阐述

原文:http://hxraid.iteye.com/blog/667437 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等. 当多个线程同时读写同一份共享资源的时候,可能会引起冲突.这时候,我们需要引入线程“同步”机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团. 同步这个词是从英文synchronize

Linux内核同步机制

http://blog.csdn.net/bullbat/article/details/7376424 Linux内核同步控制方法有很多,信号量.锁.原子量.RCU等等,不同的实现方法应用于不同的环境来提高操作系统效率.首先,看看我们最熟悉的两种机制——信号量.锁. 一.信号量 首先还是看看内核中是怎么实现的,内核中用struct semaphore数据结构表示信号量(<linux/semphone.h>中): [cpp] view plaincopyprint? struct semaph

Java并发编程实战 第15章 原子变量和非阻塞同步机制

非阻塞的同步机制 简单的说,那就是又要实现同步,又不使用锁. 与基于锁的方案相比,非阻塞算法的实现要麻烦的多,但是它的可伸缩性和活跃性上拥有巨大的优势. 实现非阻塞算法的常见方法就是使用volatile语义和原子变量. 硬件对并发的支持 原子变量的产生主要是处理器的支持,最重要的是大多数处理器架构都支持的CAS(比较并交换)指令. 模拟实现AtomicInteger的++操作 首先我们模拟处理器的CAS语法,之所以说模拟,是因为CAS在处理器中是原子操作直接支持的.不需要加锁. public s

《Java并发编程实战》第十五章 原子变量与非阻塞同步机制 读书笔记

一.锁的劣势 锁定后如果未释放,再次请求锁时会造成阻塞,多线程调度通常遇到阻塞会进行上下文切换,造成更多的开销. 在挂起与恢复线程等过程中存在着很大的开销,并且通常存在着较长时间的中断. 锁可能导致优先级反转,即使较高优先级的线程可以抢先执行,但仍然需要等待锁被释放,从而导致它的优先级会降至低优先级线程的级别. 二.硬件对并发的支持 处理器填写了一些特殊指令,例如:比较并交换.关联加载/条件存储. 1 比较并交换 CAS的含义是:"我认为V的值应该为A,如果是,那么将V的值更新为B,否则不需要修

pthread的各种同步机制

https://casatwy.com/pthreadde-ge-chong-tong-bu-ji-zhi.html pthread是POSIX标准的多线程库,UNIX.Linux上广泛使用,windows上也有对应的实现,所有的函数都是pthread打头,也就一百多个函数,不是很复杂.然而多线程编程被普遍认为复杂,主要是因为多线程给程序引入了一定的不可预知性,要控制这些不可预知性,就需要使用各种锁各种同步机制,不同的情况就应该使用不同的锁不同的机制.什么事情一旦放到多线程环境,要考虑的问题立刻

java并发编程(8)原子变量和非阻塞的同步机制

原子变量和非阻塞的同步机制 一.锁的劣势 1.在多线程下:锁的挂起和恢复等过程存在着很大的开销(及时现代的jvm会判断何时使用挂起,何时自旋等待) 2.volatile:轻量级别的同步机制,但是不能用于构建原子复合操作 因此:需要有一种方式,在管理线程之间的竞争时有一种粒度更细的方式,类似与volatile的机制,同时还要支持原子更新操作 二.CAS 独占锁是一种悲观的技术--它假设最坏的情况,所以每个线程是独占的 而CAS比较并交换:compareAndSwap/Set(A,B):我们认为内存