需要了解的关键字 寄存器 voliatile const,goto native sum.msic.Unsafe

寄存器

寄存器是CPU内部重要的数据存储资源,是汇编程序员能直接使用的硬件资源之一。
由于寄存器的存取速度比内存快,所以,在用汇编语言编写程序时,要尽可能充分利用寄存器的存储功能。
寄存器一般用来保存程序的中间结果,为随后的指令快速提供操作数,从而避免把中间结果存入内存,再读取内存的操作。在高级语言(如:C/C++语言)中,也有定义变量为寄存器类型的,这就是提高寄存器利用率的一种可行的方法。

voliatile

volatile是一个类型修饰符(type specifier)。它是被设计用来修饰被不同线程访问和修改的变量。如果没有volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。更简洁的说:用volatile之后,编译器编译时就会明白,这个变量很特殊,一定要到原来的地址去存取,不用把它优化,不会把变量放在CPU寄存器里存取而是每次存取都从它原来的内存地址去读取。

const,goto

在Java中,const是作为保留字以备扩充,同样的保留字以备扩充还有goto. 
你可以用final关键字.final也可以用于声明方法或类,被声明为final的方法或类不能被继承
一般C里是const,java用final.

native

Java不是完美的,Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能。可以将native方法比作Java程序同C程序的接口,其实现步骤: 
1.在Java中声明native()方法,然后编译.[编写带有native声明的方法的java类]
2.用javah产生一个.h文件.[使用javac命令编译所编写的java类]
3.写一个.cpp文件实现native导出方法,其中需要包含第二步产生的.h文件(注意其中又包含了JDK带的jni.h文件).[使用javah jni java类名生成扩展名为h的头文件]
4.将第三步的.cpp文件编译成动态链接库文件.[使用C/C++(或者其他编程想语言)实现本地方法]
5.在Java中用System.loadLibrary()方法加载第四步产生的动态链接库文件,这个native()方法就可以在Java中被访问了.[将C/C++编写的文件生成动态连接库]
JAVA本地方法适用的情况 
1.为了使用底层的主机平台的某个特性,而这个特性不能通过JAVA API访问 
2.为了访问一个老的系统或者使用一个已有的库,而这个系统或这个库不是用JAVA编写的 

3.为了加快程序的性能,而将一段时间敏感的代码作为本地方法实现。 

sum.msic.Unsafe

在阅读AtomicInteger的源码时,看到了这个类:sum.msic.Unsafe.Java是一个安全的开发工具,它阻止开发人员犯很多低级的错误,而大部份的错误都是基于内存管理方面的。如果你想搞破坏,可以使用Unsafe这个类。这个类是属于sun.* API中的类,并且它不是J2SE中真正的一部份,因此你可能找不到任何的官方文档,更可悲的是,它也没有比较好的代码文档。

Unsafe的源码:http://www.docjar.com/html/api/sun/misc/Unsafe.java.html

Unsafe源码中的描述如下:
A collection of methods for performing low-level, unsafe operations. Although the class and all methods are public, use of this class is limited because only trusted code can obtain instances of it.
这个类是用于执行低级别、不安全操作的方法集合。尽管这个类和所有的方法都是公开的(public),但是这个类的使用仍然受限,你无法在自己的java程序中直接使用该类,因为只有授信的代码才能获得该类的实例。
从上面的描述,可以了解到该类是用来执行较低级别的操作的,比如获取某个属性在内存中的位置,不过一般人很少会有这样的需求[如果真需要,可以通过反射机制拿到Unsafe中的一个静态属性theUnsafe ,这个静态属性本身已经初始化了,所以拿到以后可以直接使用。具体参见:http://blog.csdn.net/fenglibing/article/details/17138079]。

在AtomicInteger的源码中相关的代码如下:
// setup to use Unsafe.compareAndSwapInt for updates  
private static final Unsafe unsafe = Unsafe.getUnsafe(); 

?
1
2
// setup to use Unsafe.compareAndSwapInt for updates 
private static final Unsafe unsafe = Unsafe.getUnsafe();
上面这行代码是获取Unsafe实例的。一般情况下,我们是拿不到该类的实例的,当然jdk库里面是可以随意使用的。
?
1
2
3
4
5
6
static
      try
        valueOffset = unsafe.objectFieldOffset 
            (AtomicInteger. class .getDeclaredField( "value" )); 
      } catch (Exception ex) { throw new Error(ex); } 
    }
上面这几行代码,是用来获取AtomicInteger实例中的value属性在内存中的位置。这里使用了Unsafe的objectFieldOffset方法。这个方法是一个本地方法, 该方法用来获取一个给定的静态属性的位置。
public native long objectFieldOffset(Field f); 
这里有个疑问,为什么需要获取属性在内存中的位置?通过查看AtomicInteger源码发现,在这样几个地方使用到了这个valueOffset值:
?
1
2
3
public final void lazySet( int newValue) { 
         unsafe.putOrderedInt( this , valueOffset, newValue); 
     }
?
1
2
3
public final boolean compareAndSet( int expect, int update) { 
     return unsafe.compareAndSwapInt( this , valueOffset, expect, update); 
     }
?
1
2
3
public final boolean weakCompareAndSet( int expect, int update) { 
     return unsafe.compareAndSwapInt( this , valueOffset, expect, update); 
     }

查找资料后,发现lazySet方法大多用在并发的数据结构中,用于低级别的优化。

compareAndSet这个方法多见于并发控制中,简称CAS(Compare And Swap),意思是如果valueOffset位置包含的值与expect值相同,则更新valueOffset位置的值为update,并返回true,否则不更新,返回false。
这里可以举个例子来说明compareAndSet的作用,

如支持并发的计数器,在进行计数的时候,首先读取当前的值,假设值为a,对当前值 +1得到b,但是+1操作完以后,并不能直接修改原值为b,因为在进行+1操作的过程中,可能会有其它线程已经对原值进行了修改,所以在更新之前需要判断原值是不是等于a,如果不等于a,说明有其它线程修改了,需要重新读取原值进行操作,如果等于a,说明在+1的操作过程中,没有其它线程来修改值,我们就可以放心的更新原值了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值