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关键字的更多相关文章

  1. Java多线程初学者指南(6):慎重使用volatile关键字

    volatile关键字相信了解Java多线程的读者都很清楚它的作用,和sychnorized 一样用于多线程的同步.volatile关键字用于声明简单类型变量,如int.float.boolean等数 ...

  2. java多线程-慎重使用volatile关键字

    Java语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量.这两种机制的提出都是为了实现代码线程的安全性.其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低),而 ...

  3. java 轻量级同步volatile关键字简介与可见性有序性与synchronized区别 多线程中篇(十二)

    概念 JMM规范解决了线程安全的问题,主要三个方面:原子性.可见性.有序性,借助于synchronized关键字体现,可以有效地保障线程安全(前提是你正确运用) 之前说过,这三个特性并不一定需要全部同 ...

  4. java内存模型(线程,volatile关键字和sychronized关键字)

    volatile关键字 用在多线程,同步变量. 线程为了提高效率,将某成员变量(如A)拷贝了一份(如B),线程中对A的访问其实访问的是B.只在某些动作时才进行A和B的同步.因此存在A和B不一致的情况. ...

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

    Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...

  6. volatile关键字 学习记录2

    public class VolatileTest2 implements Runnable{ volatile int resource = 0; public static void main(S ...

  7. volatile关键字 学习记录1

    虽然已经工作了半年了...虽然一直是在做web开发....但是平时一直很少使用多线程..... 然后最近一直在看相关知识..所以就有了这篇文章 用例子来说明问题吧 public class Volat ...

  8. 【转】Java并发编程:volatile关键字解析

    转自:http://www.importnew.com/18126.html#comment-487304 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备 ...

  9. 架构师养成记--4.volatile关键字

    volatile修饰的变量可在多个线程间可见. 如下代码,在子线程运行期间主线程修改属性值并不对子线程产生影响,原因是子线程有自己独立的内存空间,其中有主内存中的变量副本. public class ...

随机推荐

  1. composer require 本地包(用于开发使用)

    修改 composer.json "repositories": [ { "type": "path", "url": ...

  2. Python 基础数据类型之tuplu

    Python的元组与列表类似,不同之处在于元组的元素不能修改. 元组使用小括号,列表使用方括号. 1.元组的定义 tuple1 = ("hello", "world&qu ...

  3. bzoj千题计划208:bzoj3174: [Tjoi2013]拯救小矮人

    http://www.lydsy.com/JudgeOnline/problem.php?id=3174 按a+b从小到大排序,a+b小的在上面,先考虑让它逃出去 正确性不会证 感性理解一下,最后一个 ...

  4. Yii 自定义模型路径

    例如现有两个 Yii 项目,分别是 test1 和 test2.在 test1 中,已经有模型了,test2 直接调用 test1 中的模型,其实添加个别名,然后修改下配置即可. 先在 index.p ...

  5. [转载]DOMContentLoaded与interactive

    http://www.cnblogs.com/muxrwc/archive/2011/01/13/1934379.html ie中inline script执行时竟然第一次进入页面,doc.ready ...

  6. ASP.NET中异常处理的注意事项

    一.ASP.NET中需要引发异常的四类情况 1.如果运行代码后,造成内存泄漏.资源不可用或应用程序状态不可恢复,则引发异常.Console这个类中,有很多类似这样的代码: if ((value < ...

  7. 【51Nod】1510 最小化序列 贪心+动态规划

    [题目]1510 最小化序列 [题意]给定长度为n的数组A和数字k,要求重排列数组从而最小化: \[ans=\sum_{i=1}^{n-k}|A_i-A_{i+k}|\] 输出最小的ans,\(n \ ...

  8. NIO学习(1)-入门学习

    一.NIO概念 IO:标准IO,也既阻塞式IO NIO:非阻塞式IO 二.NIO与标准IO的IO工作方式 标准IO基于字节流和字符流进行操作 NIO是基于通道(Channel)和缓冲区(Buffer) ...

  9. HDU 2093 考试排名 模拟题

    解题报告: 题目描述:写一个程序给一个编程考试C++实时提交系统排名,给你的数据是题目的总数,每次错误提交罚的时间分,每位用户的姓名,然后是输入用户每题的完成情况,有一下几种情况,第一,输入只有一个正 ...

  10. 第8月第12天 python json.dumps danmu

    1.json.dumps return JsonResponse({ 'status': WechatMessage.POST_METHOD_REQUIRED[1], 'status_code': W ...