一、复习
- synchronized和volatile的不同点,相同点
- volatile不能保证原子性,只能保证内存可见性
- volatile在什么情况下可以使用(两种情况)
- ABA问题定义,产生原因以及消除方法
- Java中的CAS操作
- unsafe类中的boolean objectFieldOffset(Field field),boolean compareAndSwapLong(Object obj,long offset,long expect,long update),int arrayBaseOffset(Class arrayClass),int arrayIndexOffset(Class arrayClass)
二、Unsafe类中的其他方法
1.public native long getLongvolatile(Object obj,long offset)
- 该方法用于获取对象obj地址偏移量为offset长度的对应volatile语义的值
2.void putLongvolatile(Object obj,long offset,long value)
- 该方法用于在对象obj地址偏移量为offset长度的类型为long的field值设置为value,支持volatile
3.void putOrderedLong(Object obj,long offset,long value)
- 该方法用于在对象obj地址偏移量为offset长度的类型为long的field值设置为value,这是一个有延迟的putLongvolatile方法,并且不能保证其他线程也能看到,只有被volatile修饰并有可能被意外修改的时候才会使用这个方法
4.void park(boolean isAbsolute,long time)
- 如果isAbsolute为false,time=0,表示当前线程一直阻塞
- 如果isAbsolute为false,time>0,表示当前线程阻塞time时间后,会被唤醒
注意:这时的time是一个时间段,也就是调用开始到time用完
- 如果isAbsolute为true,time>=0,表示当前线程time时间后阻塞停止,被唤醒,这里的time是绝对时间,会换算称ms单位的一个时间点
- 另外当其他线程调用了该线程的nterrupt()方法之后,该线程会返回;
- 如果其他线程调用了unpark方法,并且把该线程作为参数传入unpark方法中,那么该线程也会返回
5.void unpark(Thread thread)
- 唤醒调用park方法的阻塞状态的thread线程。
6.long getAndSetLong(Object obj,long offset,long update)
- 获取对象obj中偏移量为offset的变量volatile语义的当前值,并且设置volatile语义的值为update
public final long getAndSetLong(Object obj,long offset,long update){
long l;
do{
l=getLongvolatile(obj,offset);
}while(!compareAndSwapLong(obj,offset,l,update);
return l;
}
- 这里的循环是考虑到在多线程的环境下CAS操作会出现失败的情况,因此多次判断一下获取正确的值
7.long getAndAddLong(Object obj,long offset,long addValue)
- 该函数用于获取对象obj在其偏移量为offset的volatile变量的语义,并且该值赋值为原值加addValue
public final long getAndAddLong(Object obj,long offset,long addValue){
long l;
do{
l = getLongvolatile(obj,offset);
}while(!compareAndSwapLong(obj,offset,l,l+addValue);
return l;
}
三、直接对Unsafe类举例
package com.ruigege.OtherFoundationOfConcurrent2;
import jdk.internal.misc.Unsafe;
public class TestUnsafe {
static final Unsafe unsafe = Unsafe.getUnsafe();
static final long state = 0;
static final long stateOffset=0;
//unsafe实例内部属性state的偏移量
static {
try {
stateOffset = unsafe.objectFieldOffset(Unsafe.class.getDeclaredField("state"));
}catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
TestUnsafe testUnsafe = new TestUnsafe();
Boolean success = unsafe.compareAndSwapInt(testUnsafe,stateOffset,0,1);
System.out.println(success);
}
}
- 基本符合预期
四 、源码:
- 所在包:com.ruigege.OtherFoundationOfConcurrent2
https://github.com/ruigege66/ConcurrentJava
- CSDN:https://blog.csdn.net/weixin_44630050
- 博客园:https://www.cnblogs.com/ruigege0000/
- 欢迎关注微信公众号:傅里叶变换,个人账号,仅用于技术交流