一、复习
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/ 欢迎关注微信公众号:傅里叶变换,个人账号,仅用于技术交流