java多线程-慎重使用volatile关键字
Java语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量。这两种机制的提出都是为了实现代码线程的安全性。其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低),而且其使用也更容易出错。
public volatile boolean exit = false;
在定义exit时,使用了一个Java关键字volatile,这个关键字的目的是使exit同步,也就是说在同一时刻只能由一个线程来修改exit的值.
volatile关键字用于声明简单类型变量,如int、float、boolean等数据类型。如果这些简单数据类型声明为volatile,对它们的操作就会变成原子级别的。但这有一定的限制。例如,下面的例子中的n就不是原子级别的:
package junit.test;
public class ThreadVolatile extends Thread {
public static volatile int n = 0;
public void run() {
for (int i = 0; i < 10; i++)
try {
n = n + 1;
sleep(3); // 为了使运行结果更随机,延迟3毫秒
} catch (Exception e) {
}
}
public static void main(String[] args) throws Exception {
Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++)
// 建立100个线程
threads[i] = new ThreadVolatile();
for (int i = 0; i < threads.length; i++)
// 运行刚才建立的100个线程
threads[i].start();
for (int i = 0; i < threads.length; i++)
// 100个线程都执行完后继续
threads[i].join();
System.out.println("n=" + ThreadVolatile.n);
}
}
如果对n的操作是原子级别的,最后输出的结果应该为n=1000,而在执行上面代码时,很多时侯输出的n都小于1000,这说明n=n+1不是原子级别的操作。原因是声明为volatile的简单变量如果当前值由该变量以前的值相关,那么volatile关键字不起作用,也就是说如下的表达式都不是原子操作:
n = n + 1;
n++;
如果要想使这种情况变成原子操作,需要使用synchronized关键字,如上的代码可以改成如下的形式:
package junit.test;
public class ThreadVolatile2 extends Thread {
public static volatile int n = 0;
public static synchronized void inc() {
n++;
}
public void run() {
for (int i = 0; i < 10; i++)
try {
inc(); // n = n + 1 改成了 inc();
sleep(3); // 为了使运行结果更随机,延迟3毫秒
} catch (Exception e) {
}
}
public static void main(String[] args) throws Exception {
Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++)
// 建立100个线程
threads[i] = new ThreadVolatile2();
for (int i = 0; i < threads.length; i++)
// 运行刚才建立的100个线程
threads[i].start();
for (int i = 0; i < threads.length; i++)
// 100个线程都执行完后继续
threads[i].join();
System.out.println("n=" + ThreadVolatile2.n);
}
}
上面的代码将n=n+1改成了inc(),其中inc方法使用了synchronized关键字进行方法同步。因此,在使用volatile关键字时要慎重,并不是只要简单类型变量使用volatile修饰,对这个变量的所有操作都是原来操作,当变量的值由自身的上一个决定时,如n=n+1、n++等,volatile关键字将失效,只有当变量的值和自身上一个值无关时对该变量的操作才是原子级别的,如n = m + 1,这个就是原级别的。所以在使用volatile关键时一定要谨慎,如果自己没有把握,可以使用synchronized来代替volatile。
java多线程-慎重使用volatile关键字的更多相关文章
- java多线程4:volatile关键字
上文说到了 synchronized,那么就不得不说下 volatile关键字了,它们两者经常协同处理多线程的安全问题. volatile保证可见性 那么volatile的作用是什么呢? 在jvm运行 ...
- java 多线程11:volatile关键字
直接先举一个例子普通的线程实例变量的非可见性: public class MyThread28 extends Thread { private boolean isRunning = true; p ...
- Java并发编程:volatile关键字解析
Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...
- 【转】Java并发编程:volatile关键字解析
转自:http://www.importnew.com/18126.html#comment-487304 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备 ...
- (转)Java并发编程:volatile关键字解析
转:http://www.cnblogs.com/dolphin0520/p/3920373.html Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或 ...
- 《转》JAVA并发编程:volatile关键字解析
volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以 ...
- 【转载】Java并发编程:volatile关键字解析(写的非常好的一篇文章)
原文出处: 海子 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volat ...
- Java并发编程:volatile关键字解析(转载)
转自https://www.cnblogs.com/dolphin0520/p/3920373.html Java并发编程:volatile关键字解析 Java并发编程:volatile关键字解析 ...
- Java并发编程:volatile关键字解析zz
volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以 ...
随机推荐
- 接口测试框架——第二篇-python读取excel文件内容
今天完善excel_module.py文件,上代码: # coding: utf-8 import xlrd class ReadExcel(): def __init__(self, file_na ...
- orientdb 图数据库docker 安装试用
1. 镜像 docker pull orientdb 2. 启动 docker run -d --name orientdb -p 2424:2424 -p 2480:2480 -e ORIENTDB ...
- Python 函数 -globals()
globals() globals() 函数会以字典类型返回当前位置的全部全局变量. 实例: >>>a='runoob' >>> print(globals()) ...
- cookie控制登陆时间
使用cookie实现永久登陆 1,在cookie里面保存账号密码然后和数据库核对(由于我没有使用数据库,就不用了 2,在cookie里面保存时间戳和账号使用加密解密(我也没有使用时间戳 思路,requ ...
- Java 设计模式之建造者模式(四)
原文地址:Java 设计模式之建造者模式(四) 博客地址:http://www.extlight.com 一.前言 今天继续介绍 Java 设计模式中的创建型模式--建造者模式.上篇设计模式的主题为 ...
- js继承方式及其优缺点?
原型链继承的缺点一是字面量重写原型会中断关系,使用引用类型的原型,并且子类型还无法给超类型传递参数.借用构造函数(类式继承)借用构造函数虽然解决了刚才两种问题,但没有原型,则复用无从谈起.所以我们需要 ...
- Go的List操作上的一个小“坑”
转自http://sharecore.net/blog/2014/01/09/the-trap-in-golang-list/ 一直想不清楚一个问题,简单设计的东西到底是“坑多”还是“坑少”呢? 复杂 ...
- Vue.js实现数据的双向数据流
众所周知,Vue.js一直使用的是单向数据流的,和angularJs的双向数据流相比,单向数据流更加容易控制.Vue.js允许父组件通过props属性传递数据到子组件.但是有些情况下我们需要在子组件里 ...
- python下很帅气的爬虫包 - Beautiful Soup 示例
先发一下官方文档地址.http://www.crummy.com/software/BeautifulSoup/bs4/doc/ 建议有时间可以看一下python包的文档. Beautiful Sou ...
- linux用户,组,文件等操作
参考: https://blog.csdn.net/chengqiuming/article/details/78601977 , https://www.cnblogs.com/123-/p/4 ...