`

Java并发包Atomic 及Unsafe

 
阅读更多

  Java.util.concurrent.atomic下,有一堆AtomicXxxx对象。对于这些AtomicXxxx对象的使用,大家都知道,操作是线程安全的。不过大家有没有关心在多线程应用中,这些Atomic操作的线程安全是怎么实现的,究竟虚拟机是怎么来保证这些Atomic操作的呢?我们以AtomicLong为例,来分析Atomic操作究竟是怎么实现的。

大家可以仔细看看AtomicLong的源码,在AtomicLong中,定义了一个变量:

 

 

Private volatile long value
 

 

Volatile这个关键字的使用一直是爱恨交加,用得好的话事半功倍,如果用的不恰当则事倍功半。在此处,该value值是直接使用,不依赖外部变量的改变;并且该Value值直接放入Unsafe存储,直接和Memory打交道;和Memory打交道还有个能保证原子性的CAS的操作,所以volatile在此处使用刚好合适,volatile的其它使用场景请自行查找吧。这个value就是保存存入的值。另外还有这三个变量定义:

 

 

private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static final Boolean VM_SUPPORT_LONG_CAS;
 

Ok,这四个变量定义就能够保证对long类型的原子操作。其中VM_SUPPORT_LONG_CAS变量实际上是表示该虚拟机是否支持CAS操作。Unsafe变量和valueOffset变量才是真正进行atomic操作的关键,操作的都是value值。下面我们来仔细分析下unsafevalueOffset



Unsafe类归属于sun.misc包,是JDK内部类,是限制使用的。我们需要将compiler选项限制级别降低,才能正常引用,想看Unsafe的源码请戳这里valueOffset表示的是操作的这个数据类型的偏移量,实际上就是数据类型所占的字节数2倍。

 

我们看到源码后,想获得Unsafe的实例,于是很高兴的写下了下面这个代码:

 

 

Unsafe unsafe = Unsafe.getUnsafe();
 

Sorry,你高兴的太早了,这个方法的使用是受限的,会抛出SecurityException,根本拿不到unsafe的实例。那怎么办呢?没关系,我们有万能的Reflection操作来实现。


正确的获得unsafe实例的代码应该如下:

 

 

       Unsafe unsafe = null;
        try {
            Field field;
            field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            unsafe = (Unsafe) field.get(null);
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
 

 

看到unsafe的定义是private static final,这样的定义也能通过反射得到,那么变量作用范围声明关键字privateprotected还有什么用呢?以后大家如果想拿到某个被限制获得的类的话,要优先考虑reflection哦。其实我想说的是范围声明的关键字设定在reflection面前形同虚设,不知道这是不是符合Java的初衷,一家之言,仅供参考。


点开Unsafe源码,看到通篇native方法,仅有的几个非native方法,你再多看下还是native调用。这个native声明大家都不陌生,我们先看下的使用

 

 

 

        long value = 20121221L;
        byte size = 1;
        long address = unsafe.allocateMemory(size);
        System.out.println("Address:" + address);
        unsafe.putLong(address, value);
        long readValue = unsafe.getAddress(address);
        System.out.println("Value:" + readValue);
 

 

这个native方法的实现依赖于JVM,实现方法无从得知,但是从方法名字上可以看出来,这个unsafe实际上操作的是JVM的内存分配allocate、管理putget、拷贝copy、重分配reallocate和释放free。这个分配的内存没有进行初始化,并且能够自动类型对齐。很明显,这个操作和和Javanew Object操作完全不一样,反而和C++new操作一致;这块内存需要用户自己申请,自己进行操作。不同的是C++申请的是系统内存,而unsafe申请的是JVM控制的空间,那么这个native block是申请在stack上还是申请在heap上呢?大家可以思考一下。


看到这里,大家应该对于atomic原子操作的底层有了解了吧。其实Java也是可以通过APIC++一样直接操作虚拟机内存的。如果以后谁在告诉你Java不能直接操作内存的话,你可以以此为例给Ta一个耳光;更准确的应该说他们没有全部说对,应该说Java可以直接操作虚拟机控制的内存。


好吧,通过Unsafe操作确实能够保证赋值、读值的原子操作,等等,这就完了?No,麻烦大家看下AtomicXxxx的 getAndSet、 getAndIncrement、 getAndDecrement、  getAndAdd等方法操作,发现并不是直接委托给unsafe处理,而是添加了一些额外的操作。这些额外的操作究竟是什么意思?用的还是循环处理操作直到成功为止。这个操作有什么玄机,或者说其它的理论支持呢?且看我们下次分析。


 

 

 

 

 

 

 

分享到:
评论

相关推荐

    java5 并发包 (concurrent)思维导图

    Java 5并发包(`java.util.concurrent`,简称`Concurrent`包)是Java平台中用于多线程编程的重要组成部分,它提供了丰富的并发工具类,极大地简化了在多线程环境下的编程工作。这个包的设计目标是提高并发性能,减少...

    java线程-Atomic的含义及示例_.docx

    java线程-Atomic的含义及示例_.docx

    sun.misc.Unsafe源码

    例如,`compareAndSwapX`系列方法(如`compareAndSwapInt`)可以实现无锁更新,这是Java并发包中的`Atomic`类的基础。 4. **内存屏障**:`Unsafe`还提供了内存屏障操作,如`storeFence`和`loadFence`,它们在多线程...

    Java多线程atomic包介绍及使用方法

    Java 多线程 atomic 包介绍及使用方法 Java 多线程 atomic 包是 Java 并发编程中的一种重要工具,自从 JDK 1.5 开始,Java 就提供了 java.util.concurrent.atomic 包,方便程序员在多线程环境下,无锁的进行原子...

    浅谈Java中的atomic包实现原理及应用

    Java中的atomic包实现原理及应用 本文主要介绍了Java中的atomic包实现原理及应用,涉及Atomic在硬件上的支持、Atomic包简介及源码分析等相关内容。 Atomic在硬件上的支持 在单处理器系统中,能够在单条指令中...

    Java Atomic类及线程同步新机制原理解析

    "Java Atomic类及线程同步新机制原理解析" Java Atomic类 Java Atomic类是Java并发编程中的一种机制,用于实现原子操作。Atomic类提供了一种无锁的方式来实现线程安全的操作。Atomic类使用CAS(Compare-And-Swap)...

    Java并发编程实践-03章-使用JDK并发包构建程序1

    JDK并发包(java.util.concurrent)提供了丰富的工具和类,使得开发人员能够有效地管理和控制并发执行的任务。本章将深入探讨如何使用JDK并发包来构建程序。 **3.1 java.util.concurrent概述** `java.util....

    concurrent-resource-test:Java并发包源码学习

    Java并发包(java.util.concurrent)提供了丰富的类和接口,用于处理多线程环境下的同步、互斥以及线程间的协作。这个"concurrent-resource-test"项目很可能是为了深入理解和实践Java并发包中的源码而设计的。下面...

    natural-selection-simulation:使用Java并发包的自然选择模拟

    《自然选择模拟:Java并发包的应用解析》 自然选择模拟是一种用计算机程序模拟生物进化过程的方法,它基于达尔文的自然选择理论,用于理解和探索复杂系统的行为。在本项目"natural-selection-simulation"中,开发者...

    Java并发编程包中atomic的实现原理示例详解

    Java并发编程包中atomic的实现原理示例详解 Java并发编程包中atomic的实现原理示例详解,主要是讲解Java并发编程包中atomic的实现原理的示例代码。下面将详细地介绍atomic的实现原理。 一、线程安全 线程安全是指...

    Java多线程Atomic包操作原子变量与原子类详解

    主要介绍了Java多线程Atomic包操作原子变量与原子类详解,简单介绍了Atomic,同时涉及java.util.concurrent中的原子变量,Atomic类的作用等相关内容,具有一定参考价值,需要的朋友可以了解下。

    深入了解Java atomic原子类的使用方法和原理

    在Java中,Atomic原子类使用Unsafe类的compareAndSwapInt方法来实现CAS算法。compareAndSwapInt方法将当前的值与预期的值进行比较,如果相等,则更新当前的值。 volatile关键字 在Atomic原子类中,使用volatile...

    java并发编程与实践

    3. **并发工具类**:Java并发包(java.util.concurrent)包含了许多工具类,如Semaphore(信号量)、CyclicBarrier(回环屏障)、CountDownLatch(计数器门锁)和ThreadPoolExecutor(线程池)。这些工具可以帮助...

    Java并发编程ppt.rar

    4. **Atomic类**:Java并发包`java.util.concurrent.atomic`中的Atomic类提供了一组原子操作,如`AtomicInteger`、`AtomicLong`等,这些类的实例变量更新时具有原子性,可以替代`synchronized`进行简单同步。...

    java多线程编程实例_Source

    Java并发包(java.util.concurrent)提供了一系列线程安全的集合,如ConcurrentHashMap、CopyOnWriteArrayList等。这些集合在多线程环境下能保证数据一致性,提高性能。实例将演示如何在多线程环境中正确使用这些...

    Java并发编程从入门到精通源码.rar

    此外,Java并发包`java.util.concurrent`提供了丰富的高级并发工具,如`ExecutorService`、`Future`、`Callable`、`Semaphore`、`CyclicBarrier`等。这些工具可以帮助开发者更高效、安全地管理线程,实现线程池、...

    JAVA_API1.6文档(中文)

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...

    java多线程_java多线程下变量共享_

    3. `Atomic`类:Java并发包(`java.util.concurrent.atomic`)提供了如`AtomicInteger`、`AtomicLong`等原子类,它们提供了原子操作,如`incrementAndGet()`,在多线程环境下可以替代`synchronized`和`volatile`,实现...

    atomic_ops原子操作1

    原子操作 atomic_ops 介绍 atomic_ops 是 Linux 内核中的一种原子操作,用于实现原子 counter、Bit 操作和 spinlock 接口。下面将对 atomic_ops 的原子操作进行详细介绍。 atomic_t 类型 atomic_t 是一种原子...

    Java 并发包下源码阅读与自己的测试

    Java并发包,全称为`java.util.concurrent`,是Java编程语言中处理多线程和并发操作的核心工具包。这个包提供了高效、线程安全的数据结构,以及用于协调多个线程执行任务的工具类,极大地简化了并发编程。下面将详细...

Global site tag (gtag.js) - Google Analytics