Java关键字transient和volatile

1. transient
词义:短暂的
首先说说“序列化”,把一个对象的表示转化为字节流的过程称为串行化(也称为序列化,serialization),
从字节流中把对象重建出来称为反串行化(也称为为反序列化,deserialization)。
transient 为不应被串行化的数据提供了一个语言级的标记数据方法。
transient是类型修饰符,只能用来修饰字段。在对象序列化的过程中,标记为transient的变量不会被序列化。

class Test {  
    transient int a; // 不会被持久化  
    int b; // 持久化  
}  

当类Test的实例对象被序列化(比如将Test类的实例对象 t 写入硬盘的文本文件t.txt中),变量 a 的内容不会被保存,变量 b 的内容则会被保存。

一个序列化和反序列化的例子

package com.happy.object;

//创建一个可序列化类Person

import java.io.*;

public class Student implements Serializable {

    private String name;
    private String sex;
    private volatile  int age;

    public Student(String name, String sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

对应的测试类。

package com.happy.object;

import java.io.*;

//测试类
public class TestDemo {

    public static void main(String[] args) {
        //创建一个对象
        Student people = new Student("张三", "男",20);
        try {
            //实例化ObjectOutputStream对象
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:\\student.txt"));
            //将对象写入文件
            oos.writeObject(people);
            oos.flush();
            oos.close();

            //实例化ObjectInputStream对象
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:\\student.txt"));

            try {
                //读取对象people,反序列化
                Student p = (Student) ois.readObject();
                System.out.println("姓名:" + p.getName());
                System.out.println("性别:" + p.getSex());
                System.out.println("年龄:" + p.getAge());
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

2.volatile

词义:易变的
volatile也是变量修饰符,只能用来修饰变量
volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。

在此解释一下Java的内存机制
Java使用一个主内存来保存变量当前值,而每个线程则有其独立的工作内存。线程访问变量的时候会将变量的值拷贝到自己的工作内存中,这样,当线程对自己工作内存中的变量进行操作之后,就造成了工作内存中的变量拷贝的值与主内存中的变量值不同。
Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。
这样当多个线程同时与某个对象交互时,就必须要注意到要让线程及时的得到共享成员变量的变化。
而volatile关键字就是提示VM:对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。

对于volatile类型的变量,系统每次用到他的时候都是直接从对应的内存当中提取,而不会利用cache当中的原有数值,以适应它的未知何时会发生的变化,系统对这种变量的处理不会做优化——显然也是因为它的数值随时都可能变化的情况。

典型的例子

for(int i=0; i<100000; i++);  

这个语句用来测试空循环的速度的
但是编译器肯定要把它优化掉,根本就不执行
如果你写成

for(volatile int i=0; i<100000; i++);  

它就会执行了

使用建议:在两个或者更多的线程访问的成员变量上使用volatile。当要访问的变量已在synchronized代码块中,或者为常量时,不必使用。由于使用volatile屏蔽掉了VM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值