是《实战Java高并发程序设计》第4章的几点。

如果你对技术有着不折不挠的追求,应该还会特别在意incrementAndGet() 方法中compareAndSet()的实现。现在,就让我们更进一步看一下它把!

public final boolean compareAndSet(int expect, int update){
returnunsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

在这里,我们看到一个特殊的变量unsafe。它是sun.misc.Unsafe类型。从名字看,这个类应该是封装了一些不安全的操作。那什么操作是不安全的呢?学习过C或者C++的话,大家应该知道,指针是不安全的。这也是在Java中把指针去除的重要原因。如果指针指错了位置,或者计算指针偏移量时出错,结果可能是灾难性的,你很有可能会覆盖别人的内存,导致系统奔溃。

而这里的Unsafe就是封装了一些类似指针的操作。compareAndSwapInt()方法是一个navtive方法。它的几个参数含义如下:

public final native boolean compareAndSwapInt(Object o,long offset,int expected,int x);

第一个参数o为给定的对象,offset为对象内的偏移量(其实就是一个字段到对象头部的偏移量,通过这个偏移量可以快速定位字段),expected表示期望值,x表示要设置的值。如果指定的字段的值等于expected,那么就会把它设置为x。

不难看出,compareAndSwapInt()方法的内部,必然是使用CAS原子指令来完成的。此外,Unsafe类还提供了一些方法,主要有以下几个(以Int操作为例,其他数据类型是类似的):

//获得给定对象偏移量上的int值
public native int getInt(Object o, long offset);
//设置给定对象偏移量上的int值
public native void putInt(Object o, long offset, int x);
//获得字段在对象中的偏移量
public native long objectFieldOffset(Field f);
//设置给定对象的int值,使用volatile语义
public native void putIntVolatile(Object o, long offset,int x);
//获得给定对象对象的int值,使用volatile语义
public native int getIntVolatile(Object o, long offset);
//和putIntVolatile()一样,但是它要求被操作字段就是volatile类型的
public native void putOrderedInt(Object o, long offset, intx);

如果大家还记得“3.3.4 深度剖析ConcurrentLinkedQueue”一节中的描述的ConcurrentLinkedQueue实现,应该对ConcurrentLinkedQueue中的Node还有些印象。Node一些CAS操作也都是使用Unsafe类来实现的。大家可以回顾一下,以加深对Unsafe类的印象。

这里就可以看到,虽然Java抛弃了指针。但是在关键时刻,类似指针的技术还是必不可少的。这里底层的Unsafe实现就是最好的例子。但是很不幸,JDK的开发人员并不希望大家使用这个类。获得Unsafe实例的方法是调动其工厂方法getUnsafe()。但是,它的实现却是这样:

public static Unsafe getUnsafe() {
Class cc =Reflection.getCallerClass();
if(cc.getClassLoader() != null)
throw newSecurityException("Unsafe");
return theUnsafe;
}

注意加粗部分的代码,它会检查调用getUnsafe()函数的类,如果这个类的ClassLoader不为null,就直接抛出异常,拒绝工作。因此,这也使得我们自己的应用程序无法直接使用Unsafe类。它是一个JDK内部使用的专属类。

注意:根据Java 类加载器的工作原理,应用程序的类由AppLoader加载。而系统核心类,如rt.jar中的类由Bootstrap类加载器加载。Bootstrap加载器没有Java对象的对象,因此试图获得这个类加载器会返回null。所以,当一个类的类加载器为null时,说明它是由Bootstrap加载的,而这个类也极有可能是rt.jar中的类。

这本书:

【实战Java高并发程序设计 1】Java中的指针:Unsafe类的更多相关文章

  1. 【实战Java高并发程序设计 7】让线程之间互相帮助--SynchronousQueue的实现

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...

  2. 【实战Java高并发程序设计6】挑战无锁算法:无锁的Vector实现

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...

  3. 【实战Java高并发程序设计 5】让普通变量也享受原子操作

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...

  4. 【实战Java高并发程序设计 3】带有时间戳的对象引用:AtomicStampedReference

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference AtomicReference无法解决上述问题的根 ...

  5. 《实战java高并发程序设计》源码整理及读书笔记

    日常啰嗦 不要被标题吓到,虽然书籍是<实战java高并发程序设计>,但是这篇文章不会讲高并发.线程安全.锁啊这些比较恼人的知识点,甚至都不会谈相关的技术,只是写一写本人的一点读书感受,顺便 ...

  6. 《实战Java高并发程序设计》读书笔记

    文章目录 第二章 Java并行程序基础 2.1 线程的基本操作 2.1.1 线程中断 2.1.2 等待(wait)和通知(notify) 2.1.3 等待线程结束(join)和谦让(yield) 2. ...

  7. 【实战Java高并发程序设计 4】数组也能无锁:AtomicIntegerArray

    除了提供基本数据类型外,JDK还为我们准备了数组等复合结构.当前可用的原子数组有:AtomicIntegerArray.AtomicLongArray和AtomicReferenceArray,分别表 ...

  8. 《实战Java高并发程序设计》读书笔记四

    第四章 锁的优化及注意事项 1.锁性能的几点建议 减小锁持有时间: 系统持有锁时间越长锁竞争程度就越激烈,只对需要同步的方法加锁,可以减小锁持有时间进而提高锁性能. 减少锁的持有时间有助于降低锁冲突的 ...

  9. JAVA高并发程序设计笔记

    第二章 Java并行程序基础 1.join()的本质是让调用线程wait()在当前线程的对象上 2.Thread.yiedl()会使当前线程让出CPU 3.volatile保证可见性,无法保证原子性( ...

随机推荐

  1. OutofMemory之PermGen介绍

    可参考:https://my.oschina.net/benhaile/blog/214159.

  2. IOS __ 面试题

    1.下面四种内部排序算法中哪一种在最差的情况下时间复杂度最高:(B) A.快速排序 B.冒泡排序 C.堆排序 D.归并排序   2.Shell中,将command1的输出作为command2的输入应该 ...

  3. 《ASP.NET MVC高级编程(4版)》读书笔记(5)表单和HTML辅助方法

    5.1 表单使用 5.1.1 action 和 method 特性 <form action="/Home/Index">     <input name=&qu ...

  4. elasticsearch5.0.0 安装插件及配置过程

    elasticsearch5.0.0 安装插件及配置过程 由于es5.0是里程碑式的更新,所以很多变化的地方,暂时我就插件安装遇到的问题记录一下. 插件安装命令 2.3版本的安装命令 安装Marvel ...

  5. CA认证原理以及实现(上)

    转自:http://yale.iteye.com/blog/1675344 原理基础数字证书为发布公钥提供了一种简便的途径,其数字证书则成为加密算法以及公钥的载体,依靠数字证书,我们可以构建一个简单的 ...

  6. UWP学习记录8-设计和UI之控件和模式5

    UWP学习记录8-设计和UI之控件和模式5 1.日历.日期和时间控件 日期和时间控件提供了标准的本地化方法,可供用户在应用中查看并设置日期和时间值. 有四个日期和时间控件可供选择,选择的依据如下: 日 ...

  7. form表单提交问题

    1.提交后不能跳转到指定页面 jsp代码 <form class="form-horizontal" role="form"> <p clas ...

  8. 可变参数列表与printf()函数的实现

    问题 当我们刚开始学习C语言的时候,就接触到printf()函数,可是当时"道行"不深或许不够细心留意,又或者我们理所当然地认为库函数规定这样就是这样,没有发现这个函数与普通的函数 ...

  9. orm映射 封装baseDao

    是用orm映射封装自己封装dao层 思路:通过映射获得实体类的属性拼接sql语句 import java.lang.reflect.Field; import java.lang.reflect.In ...

  10. [翻译] ORMLite document -- How to Use Part (二)

    前言 此文档翻译于第一次学习 ORMLite 框架,如果发现当中有什么不对的地方,请指正.若翻译与原文档出现任何的不相符,请以原文档为准.原则上建议学习原英文文档. ----------------- ...