慎重使用volatile关键字
volatile关键字相信了解Java多线程的读者都很清楚它的作用。volatile关键字用于声明简单类型变量,如int、float、boolean等数据类型。如果这些简单数据类型声明为volatile,对它们的操作就会变成原子级别的。但这有一定的限制。例如,下面的例子中的n就不是原子级别的:
package mythread;
public class JoinThread 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 JoinThread();
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=” + JoinThread.n);
}
}
如果对n的操作是原子级别的,最后输出的结果应该为n=1000,而在执行上面积代码时,很多时侯输出的n都小于1000,这说明n=n+1不是原子级别的操作。原因是声明为volatile的简单变量如果当前值由该变量以前的值相关,那么volatile关键字不起作用,也就是说如下的表达式都不是原子操作:
n = n + 1;
n++;
如果要想使这种情况变成原子操作,需要使用synchronized关键字,如上的代码可以改成如下的形式:
package mythread;
public class JoinThread extends Thread
{
public static 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 JoinThread();
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=” + JoinThread.n);
}
}
上面的代码将n=n+1改成了inc(),其中inc方法使用了synchronized关键字进行方法同步。因此,在使用volatile关键字时要慎重,并不是只要简单类型变量使用volatile修饰,对这个变量的所有操作都是原来操作,当变量的值由自身的上一个决定时,如n=n+1、n++等,volatile关键字将失效,只有当变量的值和自身上一个值无关时对该变量的操作才是原子级别的,如n = m + 1,这个就是原级别的。所以在使用volatile关键时一定要谨慎,如果自己没有把握,可以使用synchronized来代替volatile。
慎重使用volatile关键字的更多相关文章
- Java多线程初学者指南(6):慎重使用volatile关键字
volatile关键字相信了解Java多线程的读者都很清楚它的作用,和sychnorized 一样用于多线程的同步.volatile关键字用于声明简单类型变量,如int.float.boolean等数 ...
- java多线程-慎重使用volatile关键字
Java语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量.这两种机制的提出都是为了实现代码线程的安全性.其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低),而 ...
- java 轻量级同步volatile关键字简介与可见性有序性与synchronized区别 多线程中篇(十二)
概念 JMM规范解决了线程安全的问题,主要三个方面:原子性.可见性.有序性,借助于synchronized关键字体现,可以有效地保障线程安全(前提是你正确运用) 之前说过,这三个特性并不一定需要全部同 ...
- java内存模型(线程,volatile关键字和sychronized关键字)
volatile关键字 用在多线程,同步变量. 线程为了提高效率,将某成员变量(如A)拷贝了一份(如B),线程中对A的访问其实访问的是B.只在某些动作时才进行A和B的同步.因此存在A和B不一致的情况. ...
- Java并发编程:volatile关键字解析
Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...
- volatile关键字 学习记录2
public class VolatileTest2 implements Runnable{ volatile int resource = 0; public static void main(S ...
- volatile关键字 学习记录1
虽然已经工作了半年了...虽然一直是在做web开发....但是平时一直很少使用多线程..... 然后最近一直在看相关知识..所以就有了这篇文章 用例子来说明问题吧 public class Volat ...
- 【转】Java并发编程:volatile关键字解析
转自:http://www.importnew.com/18126.html#comment-487304 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备 ...
- 架构师养成记--4.volatile关键字
volatile修饰的变量可在多个线程间可见. 如下代码,在子线程运行期间主线程修改属性值并不对子线程产生影响,原因是子线程有自己独立的内存空间,其中有主内存中的变量副本. public class ...
随机推荐
- Jenkins-Pipeline 流水线发布
基于docker部署 1.部署jenkins $ yum -y install java $ java -version openjdk version "1.8.0_181" O ...
- 风控3—iv算法详细解释
python信用评分卡(附代码,博主录制) https://study.163.com/course/introduction.htm?courseId=1005214003&utm_camp ...
- UnicodeDecodeError gbk codec can't decode byte in position illegal multibyte sequence
UnicodeDecodeError:'gbk' codec can't decode byte in position : illegal multibyte sequence 觉得有用的话,欢迎一 ...
- bzoj千题计划206:bzoj1076: [SCOI2008]奖励关
http://www.lydsy.com/JudgeOnline/problem.php?id=1076 很容易想到方程 dp[i][j]表示抛出了i个宝物,已选宝物状态为j的期望最大得分 初始化dp ...
- python 基础 元组()
# 元组 应用场景 # 尽管 Python的列表中可以存储不同类型的数据 # 但是在开发中,更多的应用场景是 # 1.列表存储相同类型的数据 # 2.通过迭代遍历,在循环体内部,针对列表中的每一项元素 ...
- 在html5 canvas的destination-atop属性的一些奇怪的问题
最近在整理canvas的时候发现HTML5 Canvas开发详解一个奇怪的属性解释 目标图形是显示在画布上的位图 而原图形是指要回执在画布上的形状 w3school上面是这样说的 destinatio ...
- CS229 笔记02
CS229 笔记02 公式推导 $ {\text {For simplicity, Let }} A, B, C \in {\Bbb {R}}^{n \times n}. $ $ {\bf {\t ...
- Linux - sed 常用操作
sed 文本常用操作方式 sed 10q # 显示文件中的前10行 (模拟"head") sed -n '$=' # 计算行数(模拟 "wc -l") sed ...
- opacity设定图片透明度
实例 1 - 创建透明图像 定义透明效果的 CSS3 属性是 opacity. 首先,我们将展示如何通过 CSS 来创建透明图像. 常规图像: 带有透明度的相同图像: 请看下面的 CSS: img { ...
- Python实现网页截图(PyQT5)
方案说明 功能要求:实现网页加载后将页面截取成长图片涉及模块:PyQT5 PIL逻辑说明: 1:完成窗口设置,利用PyQT5 QWebEngineView加载网页地址,待网页加载完成后,调用check ...