`

Volatile

阅读更多
Volatile


一、概念

volatile : 作用是保证变量在线程间的可见性

二、
在Java中,每一个线程都会有一块工作内存去,其中存放着所有线程共享的主内存中的变量值得拷贝。当线程执行时,他在自己的工作内存区中操作这些变量。为了存取一个共享的变量,一个线程通常先获取锁定并去清除他的内存工作区,把这些共享变量从所有线程的共享内存区中正确的装入到自己所在的工作内存区中,当线程解锁时保证该工作内存区中变量的值写回到共享内存中。
package com.study.current.thread.day01;

/**
 * volatile 线程间可见
 * 不具备原子性,只可以使一个变量在多个线程间可见
 * 
 * @description 
 * 线程t1 运行,根据 isRunnable 的值去执行
 * 在Main线程中,修改 isRunnable 的值,去停止 t1 的运行
 * volatile 使两个线程间共享 变量 isRunnable 的值
 * 
 * <p>
 *  
 * 每个线程都有自己独立的运行空间,线程在运行前拷贝主线程中的变量到自己的运行空间中
 * 每次线程运行时,都去自己空间中查看运行时需要的变量的值;
 * volatile 强制	去主内存空间中读取数据
 *
 * 
 */
public class RunThread extends Thread {
	/**
	 * 不加 volatile 
	 * 运行结果:
	 *  进入 run 方法
		setValue  ---  false 
		false
		
		程序未停止
	 */
	private volatile boolean isRunnable = true ;
	
	public void setValue(boolean isRunnable){
		this.isRunnable = isRunnable ;
	}
	
	public void run() {
		System.out.println("进入 run 方法");
		while(isRunnable){
			
		}
		System.out.println("退出 run 方法");
	}
	
	
	/**
	 * @param args
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws InterruptedException {

		RunThread rt = new RunThread();
		rt.start();
		Thread.sleep(3000);
		
		rt.setValue(false);
		System.out.println("setValue  ---  false ");
		Thread.sleep(1000);
		
		System.out.println(rt.isRunnable);
	}

}



一个线程可以执行的操作有 使用user / 复制 assign / 装载loan / 存储 store / 锁定 lock / 解锁 unlock
而主内存可以执行的操作有 读 read / 写 write / 锁定 lock / 解锁 unlock ,每个操作都是原子的

volatile 的作用就是强制线程到主内存(共享内存)里去读取变量,而不去线程工作内存区中读取,
从而实现了多个线程间的变量可见。也就是满足线程安全可见性。

二、volatile 不是原子性的

volatile 关键字虽然拥有多个线程间的可见性,但是却不具备同步性(原子性)
可以算上是一个轻量级的 synchronized ,性能比 synchronized 强的多,不会造成阻塞
一般 volatile 用于只针对于多个线程可见的变量操作,并不能代替 synchronized 的同步功能

原子性的操作使用 AtomicInteger

package com.study.current.thread.day01;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * volatile 无原子性
 * 每次加1000次,加10次,最终结果为 10000
 * 运行结果不为10000
 * 
 * 
 */
public class VolatileNoAtomic extends Thread {
	public static volatile int count  ; // 此处赋值 0 ,则符合,
//	public static AtomicInteger count = new AtomicInteger(0);
	
	public static void add(){
		for(int i = 0 ; i < 1000 ; i++){
			count ++ ;
//			count.incrementAndGet();
		}
		System.out.println("add() -- count:"+count);
	}
	
	public void run(){
		add();
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {

		VolatileNoAtomic[] vn = new VolatileNoAtomic[10];
		for(int i = 0 ; i < 10 ; i ++){
			vn[i] = new VolatileNoAtomic();
		}
		
		for(int i = 0 ; i < 10 ; i++){
			vn[i].start();
		}
		
		
	}

}



四、AtomicInteger 的原子性只是当前方法的原子性保证,当多次运行时不一定能够保证
package com.study.current.thread.day01;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * atomic 只保证本身操作的原子性,不保证多次操作的原子性
 */
public class AtomicUse {

	public static AtomicInteger count = new AtomicInteger(0);
	
	/**
	 * 如果不加 synchronized
	 * 
	 * 最终输出结果依然是正确的,但过程中是不对的,
	 * 如果是原子性的,每次累加10
	 * @return
	 */
	public synchronized int add(){
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		count.addAndGet(1);
		count.addAndGet(2);
		count.addAndGet(3);
		count.addAndGet(4);
		return count.get();
		
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		final AtomicUse au = new AtomicUse();
		
		List<Thread > list = new ArrayList<Thread>(10);
		for(int i = 0 ; i < 10 ; i++){
			list.add(new Thread(new Runnable() {
				
				public void run() {
					int count = au.add();
					System.out.println(count );
				}
			})) ;
		}
		
		for(int i = 0 ; i< 10 ; i++){
			list.get(i).start();
		}
	}

}



分享到:
评论

相关推荐

    stm32 volatile变量的正确使用

    ### STM32中Volatile变量的正确使用 #### 概述 在嵌入式系统编程中,`volatile`关键字的正确使用对于确保程序的稳定性和可靠性至关重要。它主要用于标记那些可能在程序运行过程中被外部因素(如硬件中断、多线程...

    Volatile详解,深入学习Volatile

    《深入理解Volatile》 Volatile是C/C++编程语言中的一个关键字,它与const一起被称为"cv特性",用于指示变量的值可能被系统或其他线程/进程改变,从而强制编译器每次从内存中读取该变量的最新值。在多线程或嵌入式...

    volatile的用法讲解

    "volatile的用法讲解" volatile是一种特殊的变量修饰符,它告诉编译器,这个变量的值可能会被意外地改变,因此编译器不能对其进行优化,以确保每次读取该变量时都能获取最新的值。下面是volatile变量的使用场景: ...

    const,extern,static,volatile的使用

    ### const、extern、static、volatile 的使用详解 #### 一、const 的使用 **1. 为什么使用 const** `const` 关键字在 C 和 C++ 编程语言中非常常见,它用来声明一个常量或者指定某个变量的某个方面为不可变。使用...

    volatile的使用方法

    volatile 关键字在 C 语言中的使用方法 在 C 语言中,volatile 关键字是用来指定变量的存储类别的,它告诉编译器这个变量的值可能会在编译器不知道的情况下被修改,因此需要重新加载这个变量的值。volatile 关键字...

    const和volatile分析

    在C++编程语言中,`const`和`volatile`是两个非常重要的关键字,它们用于修饰变量,赋予变量特殊的属性。这两个关键字在理解程序的行为、内存模型以及多线程编程中起到至关重要的作用。在此,我们将深入探讨`const`...

    Java线程:volatile关键字

    Java 线程 volatile 关键字详解 Java™ 语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量。volatile 变量的同步性较差,但它有时更简单并且开销更低。volatile 变量可以被看作是一种 “程度较轻的 ...

    volatile源码分析1

    【volatile源码分析1】 Java中的volatile关键字是一个关键的同步机制,它在多线程编程中扮演着重要的角色。在面试和技术讨论中,volatile经常成为焦点,但其工作原理却常常引发争议。本文将从JVM、C++以及汇编语言...

    单片机C语言中volatile的作用

    ### 单片机C语言中volatile的作用 在探讨单片机C语言中`volatile`关键字的作用之前,我们首先需要理解`volatile`的基本概念及其应用场景。`volatile`是一个用于声明变量的关键字,在C语言中,使用`volatile`修饰的...

    单片机中volatile定义的作用

    单片机中volatile定义的作用 单片机中volatile定义的作用是指在单片机编程中,使用volatile关键字来定义变量,使编译器认为该变量可能会被意外地改变,从而避免编译器对该变量的优化。这样,编译器将每次都重新读取...

    C#中volatile与lock用法

    本文实例讲述了C#中volatile与lock用法,分享给大家供大家参考。具体分析如下: 一、C#中volatile volatile是C#中用于控制同步的关键字,其意义是针对程序中一些敏感数据,不允许多线程同时访问,保证数据在任何访问...

    (*(volatile_unsigned_int_ *))

    ### 宏定义与`volatile`关键字的理解 #### 1. 宏定义的解析 在给定的代码片段中,我们看到一系列宏定义被用来访问硬件寄存器。这些宏定义通常用于嵌入式系统编程中,以便以一种类型安全且易于理解的方式访问硬件...

    C中volatile_const解析

    ### C中`volatile`与`const`解析 #### 概述 在C语言中,`volatile`和`const`是两个非常重要的关键字,它们在不同的场景下有着独特的用途。掌握这两个关键字不仅能够帮助开发者写出更加高效和可靠的代码,还能够在...

    volatile_unsigned_int

    标题“volatile_unsigned_int”以及描述“讲述了volatile_unsigned_int地址映射的使用说明”指向了C语言中特殊的关键词“volatile”以及其与“unsigned int”类型的结合使用。该知识点主要涉及硬件编程,特别是在...

    从汇编角度理解volatile

    《从汇编角度理解volatile》 volatile关键字在编程中扮演着重要的角色,它主要用于多线程编程和与硬件交互的场景。通常的理解是,volatile告诉编译器不要对某个变量进行优化,每次读取该变量时都直接从内存中获取,...

    单片机-#define XBYTE ((unsigned char volatile xdata *) 0)

    本文将围绕宏定义`#define XBYTE ((unsigned char volatile xdata *) 0)`展开,深入探讨其含义、作用以及应用场景。 #### 宏定义详解 宏定义`#define XBYTE ((unsigned char volatile xdata *) 0)`主要包含以下几...

    Java并发编程:volatile关键字解析

    ### Java并发编程:volatile关键字解析 #### 一、内存模型的相关概念 在深入了解`volatile`关键字之前,我们首先需要理解计算机内存模型的一些基本概念。在现代计算机系统中,CPU为了提高执行效率,会将频繁访问的...

    C语言中关于关键字volatile的用法

    在C语言中,关键字volatile是一个非常重要的修饰符,它在程序设计中起着不可替代的作用。volatile的主要目的是告诉编译器,它所修饰的变量是易变的,可能会在程序的控制之外被改变。因此,编译器在优化代码时,不能...

    static,const,volatile用法

    ### static、const、volatile用法解析 在编程领域中,`static`、`const`、`volatile` 这三个关键字非常常见且重要。它们分别用于控制变量的作用域、可变性和不可预测性,是理解程序行为的基础之一。下面将详细介绍...

Global site tag (gtag.js) - Google Analytics