JAVA 并发实现六(Volatile的使用)
Java™ 语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量。
这两种机制的提出都是为了实现代码线程的安全性。其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低),而且其使用也更容易出错。
在JDK1.2之前,Java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别的注意的。而随着JVM的成熟和优化,现在在多线程环境下volatile关键字的使用变得非常重要。
要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:
- 对变量的写操作不依赖于当前值。
- 该变量没有包含在具有其他变量的不变式中。
package com.subject01;
public class VolatileDemo extends Object implements Runnable {
//value变量没有被标记为volatile
private int value;
//missedIt变量被标记为volatile
private volatile boolean missedIt;
//creationTime不需要声明为volatile,因为代码执行中它没有发生变化
private long creationTime;
public VolatileDemo() {
value = 10;
missedIt = false;
//获取当前时间,亦即调用Volatile构造函数时的时间
creationTime = System.currentTimeMillis();
}
public void run() {
print("entering run()");
//循环检查value的值是否不同
while ( value < 20 ) {
//如果missedIt的值被修改为true,则通过break退出循环
if ( missedIt ) {
//进入同步代码块前,将value的值赋给currValue
int currValue = value;
//在一个任意对象上执行同步语句,目的是为了让该线程在进入和离开同步代码块时,
//将该线程中的所有变量的私有拷贝与共享内存中的原始值进行比较,
//从而发现没有用volatile标记的变量所发生的变化
Object lock = new Object();
synchronized ( lock ) {
//不做任何事
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//离开同步代码块后,将此时value的值赋给valueAfterSync
int valueAfterSync = value;
print("in run() - see value=" + currValue +", but rumor has it that it changed!");
print("in run() - valueAfterSync=" + valueAfterSync);
break;
}
}
print("leaving run()");
}
public void workMethod() throws InterruptedException {
print("entering workMethod()");
print("in workMethod() - about to sleep for 2 seconds");
Thread.sleep(2000);
//仅在此改变missedIt的值
missedIt = true;
print("in workMethod() - just set missedIt=" + missedIt);
print("in workMethod() - about to sleep for 3 seconds");
// Thread.sleep(5000);
//仅在此改变value的值
value = 50;
print("in workMethod() - just set value=" + value);
print("in workMethod() - about to sleep for 5 seconds");
Thread.sleep(3000);
print("leaving workMethod()");
}
/*
*该方法的功能是在要打印的msg信息前打印出程序执行到此所化去的时间,以及打印msg的代码所在的线程
*/
private void print(String msg) {
//使用java.text包的功能,可以简化这个方法,但是这里没有利用这一点
long interval = System.currentTimeMillis() - creationTime;
String tmpStr = " " + ( interval / 1000.0 ) + "000";
int pos = tmpStr.indexOf(".");
String secStr = tmpStr.substring(pos - 2, pos + 4);
String nameStr = " " + Thread.currentThread().getName();
nameStr = nameStr.substring(nameStr.length() - 8, nameStr.length());
System.out.println(secStr + " " + nameStr + ": " + msg);
}
public static void main(String[] args) {
try {
//通过该构造函数可以获取实时时钟的当前时间
VolatileDemo vol = new VolatileDemo();
//稍停100ms,以让实时时钟稍稍超前获取时间,使print()中创建的消息打印的时间值大于0
Thread.sleep(100);
Thread t = new Thread(vol);
t.start();
//休眠100ms,让刚刚启动的线程有时间运行
Thread.sleep(100);
//workMethod方法在main线程中运行
vol.workMethod();
} catch ( InterruptedException x ) {
System.err.println("one of the sleeps was interrupted");
}
}
}
参考的帖子及文章
http://blog.csdn.net/ns_code/article/details/17101369
http://www.ibm.com/developerworks/cn/java/j-jtp06197.html (写的相当的好)
JAVA 并发实现六(Volatile的使用)的更多相关文章
- Java并发(六):volatile的实现原理
synchronized是一个重量级的锁,volatile通常被比喻成轻量级的synchronized volatile是一个变量修饰符,只能用来修饰变量. volatile写:当写一个volatil ...
- Java并发编程:volatile关键字解析
Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...
- (转)Java并发编程:volatile关键字解析
转:http://www.cnblogs.com/dolphin0520/p/3920373.html Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或 ...
- 【死磕Java并发】-----深入分析volatile的实现原理
通过前面一章我们了解了synchronized是一个重量级的锁,虽然JVM对它做了很多优化,而下面介绍的volatile则是轻量级的synchronized.如果一个变量使用volatile,则它 ...
- Java 并发编程:volatile的使用及其原理
Java并发编程系列: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程 ...
- Java并发编程:volatile关键字解析(转载)
转自https://www.cnblogs.com/dolphin0520/p/3920373.html Java并发编程:volatile关键字解析 Java并发编程:volatile关键字解析 ...
- Java并发编程:volatile关键字解析-转
Java并发编程:volatile关键字解析 转自海子:https://www.cnblogs.com/dayanjing/p/9954562.html volatile这个关键字可能很多朋友都听说过 ...
- Java并发编程:volatile关键字解析(学习总结-海子)
博文地址:Java并发编程:volatile关键字解析
- 6、Java并发编程:volatile关键字解析
Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...
随机推荐
- Asp.Net mvc筛选器中返回信息中断操作
在mvc中,使用response.end()或Response.Redirect("url"); 是无法阻止请求继续往下执行的.如果在action中,可以我们可以使用return ...
- Java基础知识强化之集合框架笔记02:集合的继承体系图解
1. 集合的继承体系图解:
- js进制转换
var n = 17; var n2 = n.toString(2); var n8 = "0" + n.toString(8); var n16 = "0x" ...
- EasyUi DataGrid 绑定数据格式问题
如果显示汇总记录则需设置页脚属性:首先设置showFooter:true, 然后后台计算出合计数据,一起传过来,类似如下:{"total":28,"rows": ...
- cookie有效期到了后,是由浏览器还是由系统还删除的
Cookie可以保持登录信息到用户下次与服务器的会话,换句话说,下次访问同一网站时,用户会发现不必输入用户名和密码就已经登录了(当然,不排除用户手工删除Cookie).而还有一些Cookie在用户退出 ...
- linux free命令建检查内存状态
前端时间发现博客服务器物理内存使用过高问题,就是使用linux free命令检查的,这次详细介绍下这个命令. 命 令: free 功能说明:显示内存状态.语 法: free [-bkmotV][-s ...
- linux jdk,java ee ,tomcat 安装配置
1.把mypagekage.iso 挂载到linux操作系统中. 在VM做好配置,使用 mount /mnt/cdrom 2.把安装文件拷贝到/home cp 文件名 /home (快捷键tab) 3 ...
- SQL IN BETWEEN操作符
IN 操作符 IN 操作符允许我们在 WHERE 子句中规定多个值. SQL IN 语法 SELECT column_name(s) FROM table_name WHERE column_name ...
- Java前端Rsa公钥加密,后端Rsa私钥解密(目前还不支持中文加密解密,其他都行)
Base64工具类,可以让rsa编码的乱码变成一串字符序列 package com.utils; import java.io.ByteArrayInputStream; import java.io ...
- 高放的c++学习笔记之函数基础
局部变量 函数里面的局部变量有普通的局部变量和局部静态变量两种. 普通局部变量变量就是正常定义在函数体内部的变量,如果返回局部变量的地址,以便于函数调用结束后还继续访问此变量的话,编译器会报warni ...