Java中原子类的实现

  Java提供的原子类是靠sun基于CAS实现的,CAS是一种乐观锁。关于乐观锁与悲观锁

  原子变量类相当于一种泛化的volatile变量,能够支持原子的和有条件的读-改-写操作。AtomicInteger表示一个int类型的值,并提供了get和set方法,这些Volatile类型的int变量在读取和写入上有着相同的内存语义。它还提供了一个原子的compareAndSet方法(如果该方法成功执行,那么将实现与读取/写入一个volatile变量相同的内存效果),以及原子的添加、递增和递减等方法。AtomicInteger表面上非常像一个扩展的Counter类,但在发生竞争的情况下能提供更高的可伸缩性,因为它直接利用了硬件对并发的支持。

AtomicInteger的实现



  AtomicInteger 是一个支持原子操作的 Integer 类,就是保证对AtomicInteger类型变量的增加和减少操作是原子性的,不会出现多个线程下的数据不一致问题。如果不使用 AtomicInteger,要实现一个按顺序获取的 ID,就必须在每次获取时进行加锁操作,以避免出现并发时获取到同样的 ID 的现象。

  接下来通过源代码来看AtomicInteger具体是如何实现的原子操作。

  首先看incrementAndGet() 方法,下面是具体的代码:

public final int incrementAndGet() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return next;
        }
 }

  通过源码,可以知道,这个方法的做法为先获取到当前的 value 属性值,然后将 value 加 1,赋值给一个局部的 next 变量,然而,这两步都是非线程安全的,但是内部有一个死循环,不断去做compareAndSet操作,直到成功为止,也就是修改的根本在compareAndSet方法里面,compareAndSet()方法的代码如下:

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

  compareAndSet()方法调用的compareAndSwapInt()方法的声明如下,是一个native方法。

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, intvar5);

  compareAndSet 传入的为执行方法时获取到的 value 属性值,next 为加 1 后的值, compareAndSet 所做的为调用 Sun 的 UnSafe 的 compareAndSwapInt 方法来完成,此方法为 native 方法,compareAndSwapInt 基于的是 CPU 的 CAS 指令来实现的。所以基于 CAS 的操作可认为是无阻塞的,一个线程的失败或挂起不会引起其它线程也失败或挂起。并且由于 CAS 操作是 CPU 原语,所以性能比较好。

  类似的,还有 decrementAndGet() 方法。它和 incrementAndGet() 的区别是将 value 减 1,赋值给next 变量。

AtomicInteger 中还有 getAndIncrement() 和 getAndDecrement() 方法,他们的实现原理和上面的两个方法完全相同,区别是返回值不同,前两个方法返回的是改变之后的值,即 next。而这两个方法返回的是改变之前的值,即 current。还有很多的其他方法,就不列举了。

时间: 2024-10-18 18:19:24

Java中原子类的实现的相关文章

java中子类继承

[[email protected] java]# vim Ostrich.java //注意文件名必须是这个,因为下面代码中只有Ostrich是public修饰符.我们要明白public的含义 class Bird { public void Fly() { System.out.println("I am bird I can fly"); } } public class Ostrich extends Bird { public void Fly() { System.out.

Java中子类和父类的构造函数?

这篇文章总结了关于Java构造的常见??问题. 1)为什么创建一个子类对象要也需要调用父类的构造函数? class Super { String s; public Super(){ System.out.println("Super"); } } public class Sub extends Super { public Sub(){ System.out.println("Sub"); } public static void main(String[] a

java中子类与基类变量间的赋值

Java中子类与基类变量间的赋值 子类对象可以直接赋给基类变量. 基类对象要赋给子类对象变量,必须执行类型转换, 其语法是: 子类对象变量=(子类名)基类对象名; 也不能乱转换.如果类型转换失败Java会抛出以下这种异常: ClassCastException package yanzheng; class Mammal{} class Dog extends Mammal {} class Cat extends Mammal{} public class TestCast { public 

c++与java中子类中调用父类成员的方法

1 java中: 2 import java.util.Scanner; 3 public class ClassTest{ 4 public static void main(String args[]){ 5 child ch=new child(2); 6 parent p=ch; 7 p.print(); 8 //p.print2();//调用错误,父类中没有改成员方法,该方法只属于子类! 9 } 10 } 11 12 class parent{ 13 int xx; 14 parent

Java:子类调用超类方法的一种特殊情况

在Java的子类中,可以通过super来明确调用超类(也即父类)的方法.但当所调用的超类的方法(1)中又调用了其它的方法(2)时,由于Java默认动态绑定,所以方法(2)调用的是子类中的方法.如下,示例(1)是一般的子类调用超类方法(即所调用的超类中的方法不再调用其它的需要动态绑定的方法),示例(2)是特殊的子类调用超类方法. 示例(1): package MyTest; import java.util.*; public class MyTest { public static void m

转:Java中子类是否可以继承父类的static变量和方法而呈现多态特性

原文地址:Java中子类是否可以继承父类的static变量和方法而呈现多态特性 静态方法 通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法,关于static方法,声明为static的方法有以下几条限制: 它们仅能调用其他的static 方法. 它们只能访问static数据. 它们不能以任何方式引用this 或super. 无论是static修饰的变量,还是static修饰的方法,我们都知道他们是属于类本身的,不是属于某一个对象的,当声明一个对象时,并不产生sta

死磕 java原子类之终结篇(面试题)

概览 原子操作是指不会被线程调度机制打断的操作,这种操作一旦开始,就一直运行到结束,中间不会有任何线程上下文切换. 原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中的一部分,将整个操作视作一个整体是原子性的核心特征. 在java中提供了很多原子类,笔者在此主要把这些原子类分成四大类. 原子更新基本类型或引用类型 如果是基本类型,则替换其值,如果是引用,则替换其引用地址,这些类主要有: (1)AtomicBoolean 原子更新布尔类型,内部使用in

死磕 java原子类之终结篇

概览 原子操作是指不会被线程调度机制打断的操作,这种操作一旦开始,就一直运行到结束,中间不会有任何线程上下文切换. 原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中的一部分,将整个操作视作一个整体是原子性的核心特征. 在java中提供了很多原子类,笔者在此主要把这些原子类分成四大类. atomic 原子更新基本类型或引用类型 如果是基本类型,则替换其值,如果是引用,则替换其引用地址,这些类主要有: (1)AtomicBoolean 原子更新布尔类型

java中子类继承父类程序执行顺序问题

Java中,new一个类的对象,类里面的静态代码块.非静态代码.无参构造方法.有参构造方法.类的一般方法等部分,它们的执行顺序相对来说比较简单,用程序也很容易验证.比如新建一个测试父类. public class FatherTest { private String name; FatherTest(){ System.out.println("--父类的无参构造函数--"); } FatherTest(String name){ this.name=name; System.out