Java提供了一种弱同步机制,即volatile变量,用来确保将变量的更新操作通知到其它线程,它是比synchronized关键字更轻的一种同步机制。在当前大多数处理器架构上,读取volatile变量只比读取非volatile变量的开销略高一些。
当一个变量被定义为volatile后,它具备两种特性,第一是保证此变量对所有线程的可见性,指当一个线程修改了这个变量的值,新值对其它线程来说是立即得知的,而普通变量不能做到这点,普通变量的值在线程间传递要通过主内存来完成,如线程A修改一个普通变量的值,然后向主内存进行回写,另外一条线程B在线程A回写完成后再从主内存进行读取操作,新变量的值才会对主线程可见。虽然volatile变量对所有线程都是可见的,但是并不代表它在多线程并发环境下是安全的。
使用volatile变量时注意,volatile变量不足以确保递增操作的原子性,除非能确保只有一个线程对变量执行写操作。也就是声明为volatile的变量当前值与该变量以前的值相关,那么volatile变量将不起作用,即下列表达式都不是原子的:
n=n+1;
n++;
如下代码:
public class MyRunnable implements Runnable { public static volatile int n = 0; public void run() { for (int i = 0; i < 10; i++) { try { n = n + 1; Thread.sleep(10); } catch (Exception e) { // TODO: handle exception } } } } public class MainTest { public static void main(String[] args) throws Exception { Thread[] threads = new Thread[100]; // 创建100个线程 for (int i = 0; i < threads.length; i++) { threads[i] = new Thread(new MyRunnable()); } // 启动100个线程 for (int i = 0; i < threads.length; i++) { threads[i].start(); } // 让100个线程都执行完 for (int i = 0; i < threads.length; i++) { threads[i].join(); } System.out.println(MyRunnable.n); } }
上面代码,如果对n的操作是原子性的,则输出n=1000,但输出结果不到1000,说明对n的更新不是线程安全的。有人说n++的指令为iinc 1,1,是原子操作,但是把上面n=n+1改成n++后还是出现线程不同步。要想把上面代码改成线程同步,可以在对n的操作中添加synchronized关键字,如下:
synchronized (MyRunnable.class) { n = n + 1; }
只有当变量的值和自身的上一个值是无关的volatile关键字才有效,如n=m+1;所以当且仅当满足下面条件时才应该使用volatile变量:
- 对变量的写入操作不依赖变量的当前值,除非能确保只有单个线程更新该变量的值
- 该变量不与其它状态变量一起纳入不变性条件中
- 在访问该变量时不需要加锁
当一个线程被volatile修饰后,它将具备下面两种特性:
1、线程可见性:当一个线程被volatile修改后,无论是否加锁,其它线程都可以看到最新的修改,而普通变量做不到这一点;
2、禁止指令重新排序优化,普通的变量仅仅保证在该方法的执行过程中所有依赋值结果的地方都能获得正确的结果,而不能保证变量赋值操作的顺序与程序代码的执行顺序一致
看下面例子:
import java.util.concurrent.TimeUnit; public class ThreadStopExample { private static boolean stop; public static void main(String[] args) throws InterruptedException { Thread workThread = new Thread(new Runnable() { @Override public void run() { int i = 0; while (!stop) { i++; System.out.println(i); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } } }); workThread.start(); TimeUnit.SECONDS.sleep(3); stop = true; } }
关于volatile更深入文章:聊聊并发(一)——深入分析Volatile的实现原理
相关推荐
Java多线程volatile关键字详解 Java多线程volatile关键字详解主要介绍了Java多线程volatile关键字的应用和原理。volatile是一种轻量同步机制,可以确保变量的可见性和顺序性,但不保证原子性。 volatile关键字的...
Java 线程 volatile 关键字详解 Java™ 语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量。volatile 变量的同步性较差,但它有时更简单并且开销更低。volatile 变量可以被看作是一种 “程度较轻的 ...
Java中的Volatile关键字详解是Java中的一种关键字,用于保证线程之间的可见性、原子性和有序性。下面是对Java中的Volatile关键字详解的知识点总结: 一、基本概念 1. 可见性:可见性是一种复杂的属性,因为可见性...
### Java并发编程:volatile关键字解析 #### 一、内存模型的相关概念 在深入了解`volatile`关键字之前,我们首先需要理解计算机内存模型的一些基本概念。在现代计算机系统中,CPU为了提高执行效率,会将频繁访问的...
`volatile`关键字在Java多线程编程中起到了重要的作用,它提供了轻量级的同步机制,保证了共享变量的可见性。然而,它并不提供原子性保证,因此在处理复合操作时需谨慎使用。在设计并发程序时,理解`volatile`的工作...
同样,当写入`volatile`变量时,会立即写回主内存,保证了多线程环境下的数据一致性。 5. **使用场景**:`volatile`常用于以下场景: - 单例模式中的双重检查锁定(Double-Check Locking),确保实例化过程线程...
Java并发编程中,volatile关键字扮演着重要的角色,它是一种轻量级的同步机制,与synchronized相比,volatile在性能上更优,因为它不会导致线程阻塞。在深入理解volatile的关键特性之前,我们需要先了解Java内存模型...
Java 中的 volatile 关键字是 Java 并发编程中的一种关键字,它用于修饰变量,确保在多线程环境下变量的可见性和有序性。volatile 关键字的主要作用是防止编译器对变量的读写优化,确保线程之间的可见性和有序性。 ...
volatile关键字可以使变量在多线程之间可见,确保变量的最新值被所有线程看到。 在Java内存模型中,内存分为主内存和工作内存,每个线程有自己的工作内存,对于要操作的数据会从主内存拷贝一份到工作内存中,默认...
`volatile`关键字在Java语言中主要用于支持多线程环境下的变量访问安全性。它主要提供了以下两个特性: 1. **可见性**:当一个线程修改了一个被`volatile`关键字修饰的变量后,其他线程能够立即感知到这一变化。 2. ...
深入理解Java中的volatile关键字 Java中的volatile关键字是一个非常重要的概念,它不仅仅在Java语言中有,在很多语言中都有的,而且其用法和语义也都是不尽相同的。volatile关键字的主要作用是提供可见性、原子性和...
总结来说,`synchronized`关键字在Java多线程编程中扮演着关键角色,确保了线程安全和数据一致性。然而,正确理解和使用它是至关重要的,避免滥用并结合其他并发控制手段,才能编写出高效且健壮的多线程程序。在实际...
volatile关键字是Java语言中的一种机制,用于保证变量在多线程之间的可见性。它是Java.util.concurrent包的核心,没有volatile就没有那么多的并发类供我们使用。本文详细解读一下volatile关键字如何保证变量在多线程...
在Java中,volatile关键字是解决多线程问题的重要工具。本文将会详细介绍volatile关键字的原理、使用场景和注意事项。 知识点1:理解多线程问题 在多线程环境下,线程安全问题是最重要的问题。Java内存模型(JMM)...
在C++中,volatile关键字的定义与Java中的volatile关键字不同。C++中的volatile关键字主要用于提供对特殊地址的稳定访问,而不是用于线程同步。 在编译器对代码的优化中,编译器可能会对代码进行修改,以提高代码的...
Java多线程volatile原理及用法解析 Java多线程volatile原理及用法解析是Java多线程编程中一个非常重要的概念。volatile关键字是Java语言中的一个关键字,它可以保证线程之间的可见性和禁止指令重排序。 保证线程...
Volatile关键字是Java语言中的一种关键字,主要用于解决多线程编程中的可见性、原子性和有序性问题。本文将详细介绍Volatile关键字的相关知识,并通过代码帮助大家更好地理解和学习。 一、基本概念 在Java内存模型...
在Java中,Volatile关键字可以用于解决可见性问题,例如在多线程环境下,一个线程修改的变量对另一个线程是可见的。但是,Volatile关键字不能解决原子性问题,例如a++操作是一个非原子操作,需要使用同步技术来让它...
总结来说,volatile关键字在Java多线程编程中起着关键作用,它提供了轻量级的同步机制,通过内存屏障保证了变量的可见性和有序性,避免了多线程环境下数据不一致的问题。但需要注意的是,volatile不能保证操作的原子...
而在多线程环境下,通过`volatile`、`synchronized`和`Lock`可以保证一定的有序性,避免指令重排序带来的问题。 ### 二、锁的互斥与可见性 1. **互斥** 锁的互斥性确保在同一时间只有一个线程可以持有特定的锁,...