最近看了一点Java多线程方面的相关知识,这里做个简单的小结,以备后面的学习做参考。今天先对volatile这个关键字做个小结。
这里主要参考了《Java多线程编程核心技术》这本书,以及博客“沉思录”(http://blog.xujin.org/bf/bf-volatile/),在此,对原创作者表示感谢。
一、概述
1、在Java中,每个线程都会有一块工作内存区,其中存放着所有线程共享的主内存中的变量值的拷贝。当线程执行时,它在自己的工作区内存中操作这些变量。为了存取一个共享的变量,一个线程通常会先获取锁定并清除它的工作区内存,把这些共享变量从所有线程的共享内存中正确的装入到它自己所在的工作区内存中,当线程解锁时,保证该工作内存中变量的值写回到共享内存中。
2、volatile的作用就是强制线程到主内存(共享内存)里去读取变量,而不去线程工作区内存里去读取,从而实现了多个线程间的变量可见,也就是满足线程安全的可见性。
根据《Java多线程编程核心技术》该书介绍,关键字volatile的主要作用是使变量在多个线程之间可见。它会强制线程从公共堆栈中取得变量的值,而不是从线程私有数据栈中取得变量的值。
二、volatile概念
1、volatile具有可见性
volatile关键字的作用是使变量在多个线程间可见。
代码示例:
如下代码所示,当isRunning没有被volatile关键字修饰的时候,程序一直循环,线程不会结束。
public class RunThread extends Thread {// isRunning没有被volatile关键字修饰private boolean isRunning = true; //①private void setRunning(boolean isRunning) {this.isRunning = isRunning;}public void run() {System.out.println( "开始进入run方法..");while (isRunning == true) {// 一直循环........}System.out.println( "while循环结束,线程停止");}public static void main(String[] args) throws InterruptedException {RunThread rt = new RunThread();rt.start();Thread.sleep( 3000);rt.setRunning( false);System.out.println( "isRunning的值已经被设置了false");Thread.sleep( 1000);System.out.println(rt.isRunning);}}当把上述代码的①处,修改为如下时:private volatile boolean isRunning = true;运行结果是isRunning修改为false之后,线程读取到isRunning = false,从而线程结束while循环,线程退出。开始进入run方法..isRunning的值已经被设置了falsewhile循环结束,线程停止false小结:(1)在Java中,每个线程都会有一块工作内存区,其中存放着所有线程共享的主内存中的变量值的拷贝。当线程执行时,它在自己的工作区内存中操作这些变量。为了存取一个共享的变量,一个线程通常会先获取锁定并清除它的内存工作区,把这些共享变量从所有线程共享内存中正确的装入到它自己所在的工作内存中,当线程解锁时,保证该工作内存中的变量的值写回到共享内存中。(2)一个线程可以执行的操作有使用(use),赋值(assign),装载(load),存储(store),锁定(lock),解锁(unlock)。而主内存可以执行的操作有读(read),写(write),锁定(lock),解锁(unlock),每个操作都是原子的。(3)volatile的作用就是强制线程到主内存(共享内存)里去读取变量,而不去线程工作区内存里去读取,从而实现了多个线程间的变量可见,也就是满足线程安全的可见性。2、volatile不具有原子性volatile关键字虽然拥有多个线程之间的可见性,但是不具备同步性,也就是原子性,可以算得上一个轻量级别的synchronized,性能要比synchronized强很多,不会造成阻塞(在很多开源框架,比如Netty的底层代码就大量的使用volatile,由此可见Netty的性能非常的不错)。但是需要注意的是,volatile用于只针对于多个线程可见的变量操作,并不能替代synchronized的同步功能。未完待续……