• Java高并发10-Unsafe类中其他方法以及测试


    一、复习

    • 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);
     }
    }
    • 基本符合预期

    四 、源码:

  • 相关阅读:
    Go从入门到精通——结构体——构造函数——结构体和类型的一系列初始化操作的函数封装
    Go从入门到精通——接口(interfce)——实现接口的条件
    Go从入门到精通——结构体(struct)——示例:使用匿名结构体分离 JSON 数据
    通过goaccess分析出nginx的访问量保存到数据库
    linux清理buffer缓存脚本
    nginx为什么配置了路径后还去/etc/nginx/html下面找静态资源
    加密算法RSA和Base64的关系
    vue 小插件记录 nanoid
    记录:uniapp 开发原生组件视频通话的总结
    makefile
  • 原文地址:https://www.cnblogs.com/ruigege0000/p/14040074.html
Copyright © 2020-2023  润新知