关键字Volatile

Volatile修饰的成员变量在每次被线程访问时,都强迫从主内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到主内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。这样当多个线程同时与某个对象交互时,就必须要注意到要让线程及时的得到共享成员变量的变化。而volatile关键字就是提示VM:对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。使用建议:在两个或者更多的线程访问的成员变量上使用volatile。当要访问的变量已在synchronized代码块中,或者为常量时,不必使用。由于使用volatile屏蔽掉了VM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。

关键字Transient

Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。transient是Java语言的关键字,用来表示一个域不是该对象串行化的一部分。当一个对象被串行化的时候,transient型变量的值不包括在串行化的表示中,然而非transient型的变量是被包括进去的。

注意static变量也是可以串行化的 

首先,让我们看一些Java serialization的代码:

 public class LoggingInfo implements java.io.Serializable
{
private Date loggingDate = new Date();
private String uid;
private transient String pwd; LoggingInfo(String user, String password)
{
uid = user;
pwd = password;
}
public String toString()
{
String password=null;
if(pwd == null)
{
password = "NOT SET";
}
else
{
password = pwd;
}
return "logon info: \n " + "user: " + uid +
"\n logging date : " + loggingDate.toString() +
"\n password: " + password;
}
}

现在我们创建一个这个类的实例,并且串行化(serialize)它 ,然后将这个串行化对象写如磁盘。

 LoggingInfo logInfo = new LoggingInfo("MIKE", "MECHANICS");
System.out.println(logInfo.toString());
try
{
ObjectOutputStream o = new ObjectOutputStream(
new FileOutputStream("logInfo.out"));
o.writeObject(logInfo);
o.close();
}
catch(Exception e) {//deal with exception} To read the object back, we can write try
{
ObjectInputStream in =new ObjectInputStream(
new FileInputStream("logInfo.out"));
LoggingInfo logInfo = (LoggingInfo)in.readObject();
System.out.println(logInfo.toString());
}
catch(Exception e) {//deal with exception}

如果我们运行这段代码,我们会注意到从磁盘中读回(read——back (de-serializing))的对象打印password为"NOT SET"。这是当我们定义pwd域为transient时,所期望的正确结果。   
现在,让我们来看一下粗心对待transient域可能引起的潜在问题。假设我们修改了类定义,提供给transient域一个默认值,   
代码如下:

public class GuestLoggingInfo implements java.io.Serializable
{
private Date loggingDate = new Date();
private String uid;
private transient String pwd; GuestLoggingInfo()
{
uid = "guest";
pwd = "guest";
}
public String toString()
{
//same as above
}
}

现在,如果我们穿行化GuestLoggingInfo的一个实例,将它写入磁盘,并且再将它从磁盘中读出,我们仍然看到读回的对象打印password 为 "NOT SET"。当从磁盘中读出某个类的实例时,实际上并不会执行这个类的构造函数,   
而是载入了一个该类对象的持久化状态,并将这个状态赋值给该类的另一个对象。

Java transient和volatile关键字的更多相关文章

  1. Java transient、Volatile关键字

    Volatile修饰的成员变量在每次被线程访问时,都强迫从主内存中重读该成员变量的值.而且,当成员变量发生变化时,强迫线程将变化值回写到主内存.这样在任何时刻,两个不同的线程总是看到某个成员变量的同一 ...

  2. java transient 和Volatile关键字

    Volatile修饰的成员变量在每次被线程访问时,都强迫从主内存中重读该成员变量的值.而且,当成员变量发生变化时,强迫线程将变化值回写到主内存.这样在任何时刻,两个不同的线程总是看到某个成员变量的同一 ...

  3. java中的volatile关键字

    java中的volatile关键字 一个变量被声明为volatile类型,表示这个变量可能随时被其他线程改变,所以不能把它cache到线程内存(如寄存器)中. 一般情况下volatile不能代替syn ...

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

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

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

    摘要: 在 Java 并发编程中,要想使并发程序能够正确地执行,必须要保证三条原则,即:原子性.可见性和有序性.只要有一条原则没有被保证,就有可能会导致程序运行不正确.volatile关键字 被用来保 ...

  6. Java中的volatile关键字的功能

    Java中的volatile关键字的功能 volatile是java中的一个类型修饰符.它是被设计用来修饰被不同线程访问和修改的变量.如果不加入volatile,基本上会导致这样的结果:要么无法编写多 ...

  7. 深入理解Java中的volatile关键字

    在再有人问你Java内存模型是什么,就把这篇文章发给他中我们曾经介绍过,Java语言为了解决并发编程中存在的原子性.可见性和有序性问题,提供了一系列和并发处理相关的关键字,比如synchronized ...

  8. java并发系列(六)-----Java并发:volatile关键字解析

    在 Java 并发编程中,要想使并发程序能够正确地执行,必须要保证三条原则,即:原子性.可见性和有序性.只要有一条原则没有被保证,就有可能会导致程序运行不正确.volatile关键字 被用来保证可见性 ...

  9. java中的Volatile关键字使用

    文章目录 什么时候使用volatile Happens-Before java中的Volatile关键字使用 在本文中,我们会介绍java中的一个关键字volatile. volatile的中文意思是 ...

随机推荐

  1. 洛谷P2754 [CTSC1999]家园(最大流)

    传送门 这题思路太强了……大佬们怎么想到的……我这菜鸡根本想不出来…… 先判断是否能到达,对每一艘飞船能到的地方用并查集合并一下,最后判断一下是否连通 然后考虑几天怎么判断,我们可以枚举. 每一个点表 ...

  2. 18.阻止默认操作e.preventDefault();防止冒泡事件:e.stopPropagation()

      一.加了e.preventDefault();会阻止a标签默认的点击跳转效果 <!DOCTYPE html> <html lang="en"> < ...

  3. 关于python中的round()和javascript中的round()的比较

    ps:python的round()和javascript的round()的比较: javascript:Math.round():正常的标准舍入,就像我们学的数学课本上面的规则 python:pyth ...

  4. XSS攻击的防御

    XSS攻击的防御 XSS 攻击是什么 XSS 又称 CSS,全称 Cross SiteScript,跨站脚本攻击,是 Web 程序中常见的漏洞,XSS 属于被动式且用于客户端的攻击方式,所以容易被忽略 ...

  5. React笔记:ref注意事项

    [一]使用ref必须用在[类型式的组件]才起作用,用在[函数式的组件]是无效的. 下面这个例子用在了[函数式的组件]上,所以是无效的: function MyFunctionalComponent() ...

  6. oracle数据库修改密码

    忘记了数据库的登录密码,oracle数据库无法登录了. 先删除原先的密码保存文件: del E:\oracle_app\Administrator\product\11.2.0\dbhome_1\da ...

  7. bzoj2190 仪仗队

    题目传送门 思路: 哪些点能被人看到,其实就是哪些点不会被其他点挡住,只要顶点的坐标互质就可以了,互质用欧拉函数算.特殊考虑一下n=1和0的情况. 欧拉函数,Φ(x)=x(1-1/p1)(1-1/p2 ...

  8. gym101201F Illumination 2-SAT

    题目传送门 题目大意: 给出n*n的网格,l栈灯,每盏灯可以选择照亮竖着的2*r+1的范围,或者横着的2*r+1的范围,要求一个格子不会同时被一盏以上的横着的灯照亮,也不能被一盏以上的竖着的灯照亮,所 ...

  9. 出现socket:(10107)系统调用失败

    在编译vue项目,npm run dev出现 socket:(10107)系统调用失败  解决方案: 以管理员身份打开cmd,使用以下命令:     netsh winsock reset 重启电脑即 ...

  10. PHP返回变量或数组的字符串表示:var_export()

    使用var_export()函数可以在服务端程序没有在打印的情况下,配合file_put_contents方便的调试程序,查看变量和数组的内容. 在开发过程中,我们常用var_dump()来打印数组内 ...