当前位置: 首页 > news >正文

volatile使用

volatile关键字的主要作用是使变量在多个线程间可见

JDK1.5开始对Thread进行了优化,对每个线程加了一块独立的内存空间。这个空间用于存放在thread中使用到的主线程中变量的副本,在线程运行过程中,直接在变量副本中操作,这样可以提高代码执行的效率。在下面代码中isRunning在线程执行过程中会使用,因此会将这个变量的副本放到线程独立的内存空间中。

public class RunThread extends Thread{

	//volatile
	private boolean isRunning = true;
	private void setRunning(boolean isRunning){
		this.isRunning = isRunning;
	}
	
	public void run(){
		System.out.println("进入run方法..");
		int i = 0;
		while(isRunning == true){
			//..
		}
		System.out.println("线程停止");
	}
	
	public static void main(String[] args) throws InterruptedException {
		RunThread rt = new RunThread();
		rt.start();
		Thread.sleep(1000);
		rt.setRunning(false);
		System.out.println("isRunning的值已经被设置了false");
	}
}

在Eclipse中console输出如下



isRunning使用volatile成员变量修饰,即private volatile boolean isRunning = true;则当变量改变时,会强制线程执行引擎去主内存里读取




下面例子,10个线程对一个静态变量进行操作,最终的结果不一定是10000

import java.util.concurrent.atomic.AtomicInteger;

/**
 * volatile关键字不具备synchronized关键字的原子性(同步)
 *
 */
public class VolatileNoAtomic extends Thread{
	private static volatile int count;
	//private static AtomicInteger count = new AtomicInteger(0);
	private static void addCount(){
		for (int i = 0; i < 1000; i++) {
			count++ ;
			//count.incrementAndGet();
		}
		System.out.println(count);
	}
	
	public void run(){
		addCount();
	}
	
	public static void main(String[] args) {
		
		VolatileNoAtomic[] arr = new VolatileNoAtomic[10];
		for (int i = 0; i < 10; i++) {
			arr[i] = new VolatileNoAtomic();
		}
		
		for (int i = 0; i < 10; i++) {
			arr[i].start();
		}
	}
}

Eclipse的console输出,运行结果如下图



为保证操作的原子性,做如下修改:

1.

//private static volatile int count;
private static AtomicInteger count = new AtomicInteger(0);//具备原子性

2.

//count++ ;
count.incrementAndGet();

run as -- java application,运行结果如下图:



volatile可以实现在多个线程之间的可见性,但是却不具备同步性(也就是原子性),可以算是一个轻量级的synchronized,性能要比synchronized强很多,不会造成阻塞(在很多开源的架构里,比如netty的底层代码就大量使用volatile,可见netty性能一定是非常不错的)。注意:一般volatile用于只针对于多个线程可见的变量操作,并不能代替synchronized的同步功能。要实现原子性建议使用atomic类的系列对象,支持原子性操作(注意:atomic类只保证本身方法原子性,并不保证多次操作的原子性)

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

public class AtomicUse {

	private static AtomicInteger count = new AtomicInteger(0);
	
	//多个addAndGet在一个方法内是非原子性的,需要加synchronized进行修饰,保证4个addAndGet整体原子性
	/**synchronized*/
	public synchronized int multiAdd(){
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			count.addAndGet(1);
			count.addAndGet(2);
			count.addAndGet(3);
			count.addAndGet(4); 
			return count.get();
	}
	
	
	public static void main(String[] args) {
		
		final AtomicUse au = new AtomicUse();

		List<Thread> ts = new ArrayList<Thread>();
		for (int i = 0; i < 10; i++) {
			ts.add(new Thread(new Runnable() {
				@Override
				public void run() {
					System.out.println(au.multiAdd());
				}
			}));
		}

		for(Thread t : ts){
			t.start();
		}
	}
}




相关文章:

  • Can not find the tag library descriptor for http://java.sun.com/jsp/jstl/ core
  • javax.servlet.jsp.JspException cannot be resolved to a type
  • 使用wait/notify模拟Queue+ThreadLocal
  • 多线程模式中的单例
  • Semaphore信号量
  • Linux中./configure、make、make install 命令
  • 无锁并行计算框架Disruptor
  • 重入锁+读写锁+公平锁+非公平锁
  • JVM各组成部分说明+相关参数设置
  • java中垃圾回收算法+垃圾收集器
  • Linux中安装Nexus+Maven
  • Oracle数据库创建实例
  • Nginx中log_format日志格式参数及说明
  • Eclispe SVN 创建分支
  • Eclipse SVN 分支合并+代码冲突处理
  • [Vue CLI 3] 配置解析之 css.extract
  • 【个人向】《HTTP图解》阅后小结
  • AWS实战 - 利用IAM对S3做访问控制
  • C++入门教程(10):for 语句
  • CSS 提示工具(Tooltip)
  • ES2017异步函数现已正式可用
  • Git的一些常用操作
  • java取消线程实例
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • python学习笔记 - ThreadLocal
  • Python中eval与exec的使用及区别
  • Swift 中的尾递归和蹦床
  • vue总结
  • webgl (原生)基础入门指南【一】
  • 机器学习 vs. 深度学习
  • 计算机常识 - 收藏集 - 掘金
  • 前端设计模式
  • 删除表内多余的重复数据
  • hi-nginx-1.3.4编译安装
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • 关于Android全面屏虚拟导航栏的适配总结
  • 没有任何编程基础可以直接学习python语言吗?学会后能够做什么? ...
  • #100天计划# 2013年9月29日
  • #QT(串口助手-界面)
  • #数学建模# 线性规划问题的Matlab求解
  • $ is not function   和JQUERY 命名 冲突的解说 Jquer问题 (
  • (1)(1.13) SiK无线电高级配置(六)
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)
  • (三)docker:Dockerfile构建容器运行jar包
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (译) 函数式 JS #1:简介
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (原)Matlab的svmtrain和svmclassify
  • (转)Linq学习笔记
  • (转)linux自定义开机启动服务和chkconfig使用方法
  • .form文件_SSM框架文件上传篇
  • .net core 依赖注入的基本用发
  • .NET开发人员必知的八个网站
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比