Java中的一些不常见的关键字

transient

对于transient 修饰的成员变量,在类的实例对象的序列化处理过程中会被忽略。 因此,transient变量不会贯穿对象的序列化和反序列化,生命周期仅存于调用者的内存中而不会写到磁盘里进行持久化。

Java中对象的序列化指的是将对象转换成以字节序列的形式来表示,这些字节序列包含了对象的数据和信息,一个序列化后的对象可以被写到数据库或文件中,也可用于网络传输。

在持久化对象时,对于一些特殊的数据成员(如用户的密码,银行卡号等 涉及安全性的数据),我们不想用序列化机制来保存它。为了在一个特定对象的一个成员变量上关闭序列化,可以在这个成员变量前加上关键字transient。

static修饰的静态变量天然就是不可序列化的。

transient关键字只能修饰变量,而不能修饰方法和类。(本地变量是不能被transient关键字修饰的。)
变量如果是用户自定义类变量,则该类需要实现Serializable接口。

volatile

volatile同样用于修饰类属性,不能用于修饰本地变量
volatile可以理解为一种轻量级的同步机制(区别于锁机制),能够减少线程上下文的切换和调度,但volatile的同步性也没有锁的强,对于一些非原子性的操作还是不能做到完全保证同步。

先来看看volatile的实现原理吧:
Java的内存模型
在这里插入图片描述
所有线程的共享变量都存储在主内存中,每一个线程都有一个独有的工作内存,每个线程不直接操作在主内存中的变量,而是将主内存上变量的副本放进自己的工作内存中,只操作工作内存中的数据。当修改完毕后,再把修改后的结果放回到主内存中。每个线程都只操作自己工作内存中的变量,无法直接访问对方工作内存中的变量,线程间变量值的传递需要通过主内存来完成。
如果对变量加上volatile关键字后,如果某线程A修改了该变量后,会立即将变量的值刷到主内存中,其他线程中的变量失效,必须从主内存中重新获取。

底层原理:
volatile可见性是通过汇编加上Lock前缀指令,触发底层的MESI缓存一致性协议来实现的。

状态描述
M 修改 (Modified)此时缓存行中的数据与主内存中的数据不一致,数据值存在于本工作内存中,其他线程从主内存中读取共享变量值的操作会被延迟执行,直到该缓存行数据将数据写回到主内存后
E 独享 (Exclusive)此时缓存行中的数据会与主内存中的数据一致,数据只存在本工作内存中。此时会监听其他线程读主内存中共享变量的操作,如果发生,该缓存行需要变成共享状态
S 共享 (Shared)此时缓存行中的数据与主内存中的数据一致,数据存在于很多工作内存中。此时会监听其他线程使该缓存行无效的请求,如果发生,该缓存行需要变成无效状态。
I 无效 (Invalid)此时该缓存行无效

简单翻译一下:获取volatile的所有线程都会监听内存总线中该变量的获取状态。如果一个线程正在对某volatile修饰的变量修改时,其他线程中的值会变为无效状态,等待修改完成,再重新去主内存中获取新的值。

在这种模式下会出现一些并发问题,例如:a++这种自增的操作,但并非原子性的情况

时间操作
1线程A获取到a
2线程B获取到a
3线程A:a++
4线程B:由于线程A的修改,导致线程B的值失效,不执行操作

因此,想完全实现同步,还需要引入锁机制

参考:CSDN博主「天瑕」的原创文章


而volatile另一个特性则是禁止指令重排序,底层原理则是在指令间通过内存屏障实现。

instanceof

判断一个对象是否是一个类的实例,返回值为true/false
ObjectName instanceof ClassName

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值