澳门新浦京娱乐游戏java多线程-06-atomic包

引言

Java从JDK1.5上马提供了java.util.concurrent.atomic包,方便程序员在多线程蒙受下,无锁的拓宽原子操作。原子变量的平底使用了计算机提供的原子指令,可是分歧的CPU结构恐怕提供的原子指令不相通,也可以有相当的大可能率供给某种形式的内部锁,所以该方式不能够相对保证线程不被窒碍。

当在四线程境况时,同临时候立异一个共享变量,大概得不到预期的结果。平时大家会使用synchronized来解决这么些主题素材。而Java从JDK
1.5从头提供了java.util.concurrent.atomic包,那几个包中的原子操作类提供了一种用法简单、品质高效、线程安全地翻新贰个变量的格局。因为变量的连串有数不胜数种,所以在Atomic包里累加提供了12个类,归于4种档期的顺序的原子更新方式,分别是原子更新为主类型、原子更新数组、原子更新援用和原子更新属性。Atomic包里的类基本都以应用Unsafe完成的包装类。

[TOC]

Atomic包介绍

在Atomic包里累加有十三个类,八种原子更新格局,分别是原子更新为主项目,原子更新数组,原子更新引用和原子更新字段。Atomic包里的类为主都以行使Unsafe完结的包装类。

原子更新基本类型类

利用原子的方法更新为主类型,Atomic包提供了以下3个类:AtomicBoolean:原子更新布尔类型。AtomicInteger:原子更新整型。AtomicLong:原子更新长整型。

下面以AtomicInteger为例举行传授,AtomicInteger的常用方法如下。·int
addAndGet(int
delta):以原子格局将输入的数值与实例中的值(AtomicInteger里的value)相加,并回到结果。·boolean
compareAndSet(int expect,int
update):要是输入的数值等于预期值,则以原子情势将该值设置为输入的值。·int
getAndIncrement(卡塔尔:以原子方式将近日值加1,注意,这里再次来到的是自增前的值。·void
lazySet(int
newValue):最后会设置成newValue,使用lazySet设置值后,恐怕产生别的线程在未来的一小段时光内仍可以够读到旧的值。·int
getAndSet(int newValue):以原子情势设置为newValue的值,并重临旧值。

public class AtomicIntegerDemo { private static AtomicInteger atomicInteger = new AtomicInteger; public static void main(String[] args) { System.out.println(atomicInteger.addAndGet;//2 System.out.println(atomicInteger.compareAndSet;//true System.out.println(atomicInteger.getAndSet;//4 System.out.println(atomicInteger.incrementAndGet;//7 System.out.println(atomicInteger.getAndIncrement;//7 System.out.println(atomicInteger.get;//8; }}

能够窥见AtomicInteger底层都以因而unsafe.compareAndSwapInt方法达成。

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

注:
Atomic包提供了3种基本项目标原子更新,不过Java的骨干类型里还大概有char、float和double等。那么难题来了,如何原子的换代任何的为主类型呢?Atomic包里的类为主都以应用Unsafe完结的,让大家一道看一下Unsafe的源码:

/*** 如果当前数值是expected,则原子的将Java变量更新成x* @return 如果更新成功则返回true*/public final native boolean compareAndSwapObject(Object o,long offset,Object expected,Object x);public final native boolean compareAndSwapInt(Object o, long offset,int expected,int x);public final native boolean compareAndSwapLong(Object o, long offset,long expected,long x);

由此代码,大家发掘Unsafe只提供了3种CAS方法:compareAndSwapObject、compareAndSwapIntcompareAndSwapLong,再看AtomicBoolean源码,开采它是先把Boolean调换到整型,再使用compareAndSwapInt进行CAS,所以原子更新char、float和double变量也得以用相近的笔触来得以完结。

转发自并发编制程序网 – ifeve.com本文链接地址:
Java中的Atomic包使用指南

原子更新基本类型类

用于通过原子的秘诀立异为主项目,Atomic包提供了以下四个类:

  • AtomicBoolean:原子更新布尔类型。
  • AtomicInteger:原子更新整型。
  • AtomicLong:原子更新长整型。

AtomicInteger的常用方法如下:

  • int addAndGet(int delta卡塔尔(قطر‎:以原子格局将输入的数值与实例中的值(AtomicInteger里的value)相加,并赶回结果
  • boolean compareAndSet(int expect, int update):若是输入的数值等于预期值,则以原子格局将该值设置为输入的值。
  • int
    getAndIncrement(卡塔尔:以原子格局将这段日子值加1,注意:这里再次来到的是自增前的值。
  • void lazySet(int
    newValue卡塔尔:最终会设置成newValue,使用lazySet设置值后,恐怕招致其余线程在事后的一小段时日内还是可以够读到旧的值。
  • int getAndSet(int
    newValueState of Qatar:以原子形式设置为newValue的值,并再次来到旧值。

AtomicInteger例子代码如下:

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerTest {

    static AtomicInteger ai = new AtomicInteger(1);

    public static void main(String[] args) {
        System.out.println(ai.getAndIncrement());
        System.out.println(ai.get());
    }

}

输出

1
2

原子更新数组

透过原子的秘籍更新数组里的某部成分,Atomic包提供了以下3个类。AtomicIntegerArray:原子更新整型数组里的要素。AtomicLongArray:原子更新长整型数组里的成分。AtomicReferenceArray:原子更新援引类型数组里的因素。

上面以AtomicIntegerArray类为例,介绍其常用艺术:int addAndGet(int
i,int delta):以原子情势将输入值与数组中索引i的元素相加。boolean
compareAndSet(int i,int expect,int
update):借使当前值等于预期值,则以原子方式将数组地方i的要素设置成update值。

 static int[] value = new int[] { 1, 2 }; static AtomicIntegerArray ai = new AtomicIntegerArray; public static void main(String[] args) { ai.getAndSet; System.out.println);//3 ai.addAndGet; System.out.println);//5 }

正文头阵于并发网,作者:方腾飞

餐后甜食

Atomic包提供了二种基本类型的原子更新,可是Java的大旨项目里还会有char,float和double等。那么难题来了,怎么样原子的翻新任何的主干项目呢?Atomic包里的类基本都是运用Unsafe完毕的,让大家一块看下Unsafe的源码,开采Unsafe只提供了二种CAS方法,compareAndSwapObject,compareAndSwapInt和compareAndSwapLong,再看AtomicBoolean源码,发掘其是先把Boolean转变到整型,再使用compareAndSwapInt进行CAS,所以原子更新double也得以用临近的思绪来促成。

原子更新援用类型

原子更新为主项指标AtomicInteger,只好更新叁个变量,假如要原子更新多少个变量,就要求运用这一个原子更新引用类型提供的类。Atomic包提供了以下3个类。AtomicReference:原子更新援用类型。AtomicReference菲尔德Updater:原子更新援引类型里的字段。AtomicMarkableReference:原子更新带有标志位的援用类型。能够原子更新二个布尔类型的标识位和援用类型。结构方法是Atomic马克ableReference(V
initialRef,booleaninitialMark)。

引言

Java从JDK1.5开首提供了java.util.concurrent.atomic包,方便程序猿在多线程境况下,无锁的扩充原子操作。原子变量的底层使用了Computer提供的原子指令,然则不一样的CPU结构恐怕提供的原子指令不等同,也许有十分的大希望需求某种情势的中间锁,所以该办法不能够相对保证线程不被封堵。

原子更新数组类

通过原子的办法更新数组里的某部成分,Atomic包提供了以下七个类:

  • AtomicIntegerArray:原子更新整型数组里的成分。
  • AtomicLongArray:原子更新长整型数组里的元素。
  • AtomicReferenceArray:原子更新引用类型数组里的成分。

AtomicIntegerArray类首要是提供原子的主意更正数组里的整型,其常用艺术如下

  • int addAndGet(int i, int
    delta卡塔尔:以原子方式将输入值与数组中索引i的要素相加。
  • boolean compareAndSet(int i, int expect, int
    updateState of Qatar:如若当前值等于预期值,则以原子格局将数组地方i的要素设置成update值。

实例代码如下:

public class AtomicIntegerArrayTest {

    static int[] value = new int[] { 1, 2 };

    static AtomicIntegerArray ai = new AtomicIntegerArray(value);

    public static void main(String[] args) {
        ai.getAndSet(0, 3);
        System.out.println(ai.get(0));
                System.out.println(value[0]);
    }

}

输出

3
1

AtomicIntegerArray类需求在意的是,数组value通过构造方法传递步向,然后AtomicIntegerArray会将前段时间数组复制一份,所以当AtomicIntegerArray对当中的数组元素进行改革时,不会听得多了就能够说的清楚到传播的数组。

原子更新字段类

纵然需原子地翻新有个别类里的有些字段时,就须求利用原子更新字段类,Atomic包提供了以下3个类进行原子字段更新。AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。AtomicLongFieldUpdater:原子更新长整型字段的更新器。AtomicStampedReference:原子更新带有版本号的援用类型。该类将整数值与引用关联起来,可用于原子的换代数据和数目标本子号,能够缓和使用CAS进行原子更新时大概现身的ABA难题。要想原子地校正字段类供给两步。第一步,因为原子更新字段类都是抽象类,每趟使用的时候必需利用静态方法newUpdater(卡塔尔国成立二个更新器,並且需求设置想要更新的类和品质。第二步,更新类的字段必得运用public
volatile修饰符。

Atomic包介绍

在Atomic包里一同有十六个类,三种原子更新方式,分别是原子更新为主项目,原子更新数组,原子更新引用和原子更新字段。Atomic包里的类为主都以使用Unsafe达成的包装类。

原子更新引用类型

原子更新为主类型的AtomicInteger,只可以更新二个变量,假若要原子的校正四个变量,就需求动用那么些原子更新援引类型提供的类。Atomic包提供了以下四个类:

  • AtomicReference:原子更新援引类型。
  • AtomicReferenceFieldUpdater:原子更新引用类型里的字段。
  • AtomicMarkableReference:原子更新带有标志位的援用类型。可以原子的换代三个布尔类型的标志位和援用类型。构造方法是AtomicMarkableReference(V
    initialRef, boolean initialMark卡塔尔(قطر‎

AtomicReference的选拔例子代码如下:

public class AtomicReferenceTest {

    public static AtomicReference<user> atomicUserRef = new AtomicReference</user><user>();

    public static void main(String[] args) {
        User user = new User("conan", 15);
        atomicUserRef.set(user);
        User updateUser = new User("Shinichi", 17);
        atomicUserRef.compareAndSet(user, updateUser);
        System.out.println(atomicUserRef.get().getName());
        System.out.println(atomicUserRef.get().getOld());
    }

    static class User {
        private String name;
        private int old;

        public User(String name, int old) {
            this.name = name;
            this.old = old;
        }

        public String getName() {
            return name;
        }

        public int getOld() {
            return old;
        }
    }
}

输出

Shinichi
17

原子更新基本类型类

用以通过原子的点子更新为主项目,Atomic包提供了以下三个类:

  • AtomicBoolean:原子更新布尔类型。
  • AtomicInteger:原子更新整型。
  • AtomicLong:原子更新长整型。

AtomicInteger的常用方法如下:

  • int addAndGet(int delta卡塔尔:以原子情势将输入的数值与实例中的值(AtomicInteger里的value)相加,并回到结果
  • boolean compareAndSet(int expect, int update卡塔尔:假诺输入的数值等于预期值,则以原子格局将该值设置为输入的值。
  • int
    getAndIncrement(State of Qatar:以原子方式将近日值加1,注意:这里再次来到的是自增前的值。
  • void lazySet(int
    newValue卡塔尔国:最终会设置成newValue,使用lazySet设置值后,只怕引致其余线程在以后的一小段时光内还能读到旧的值。关于该办法的愈多消息方可参谋并发网翻译的一篇小说《AtomicLong.lazySet是怎么着专业的?》
  • int getAndSet(int
    newValueState of Qatar:以原子格局设置为newValue的值,并赶回旧值。

AtomicInteger例子代码如下:

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerTest {

    static AtomicInteger ai = new AtomicInteger(1);

    public static void main(String[] args) {
        System.out.println(ai.getAndIncrement());
        System.out.println(ai.get());
    }

}

输出

1
2

原子更新字段类

举个例子大家只必要某些类里的某部字段,那么就须求动用原子更新字段类,Atomic包提供了以下四个类:

  • AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。
  • AtomicLongFieldUpdater:原子更新长整型字段的更新器。
  • AtomicStampedReference:原子更新带有版本号的援引类型。该类将整数值与引用关联起来,可用来原子的更数据和多少的本子号,能够缓和选拔CAS举行原子更新时,恐怕现身的ABA难点。

原子更新字段类都以抽象类,每回使用都时候必得选拔静态方法newUpdater成立贰个更新器。原子更新类的字段的总得利用public
Volatile修饰符。AtomicIntegerFieldUpdater的事例代码如下:

public class AtomicIntegerFieldUpdaterTest {

    private static AtomicIntegerFieldUpdater<User> a = AtomicIntegerFieldUpdater
            .newUpdater(User.class, "old");

    public static void main(String[] args) {
        User conan = new User("conan", 10);
        System.out.println(a.getAndIncrement(conan));
        System.out.println(a.get(conan));
    }

    public static class User {
        private String name;
        public volatile int old;

        public User(String name, int old) {
            this.name = name;
            this.old = old;
        }

        public String getName() {
            return name;
        }

        public int getOld() {
            return old;
        }
    }
}

输出

10
11

就餐之后甜点

Atomic包提供了三种基本类型的原子更新,然则Java的着力项目里还恐怕有char,float和double等。那么难题来了,怎样原子的翻新任何的中央项目呢?Atomic包里的类基本都是运用Unsafe完结的,让我们一块看下Unsafe的源码,发现Unsafe只提供了三种CAS方法,compareAndSwapObject,compareAndSwapInt和compareAndSwapLong,再看AtomicBoolean源码,开掘其是先把Boolean转换来整型,再选取compareAndSwapInt实行CAS,所以原子更新double也能够用相同的思绪来落实。

转发自并发编制程序网 – ifeve.com本文链接地址: Java中的Atomic包使用指南

参照他事他说加以考察资料

  • JDK1.6源码
  • JDK1.6API文档
  • Unsafe源码

原子更新数组类

由此原子的措施更新数组里的有个别成分,Atomic包提供了以下多少个类:

  • AtomicIntegerArray:原子更新整型数组里的成分。
  • AtomicLongArray:原子更新长整型数组里的成分。
  • AtomicReferenceArray:原子更新援引类型数组里的成分。

AtomicIntegerArray类首假如提供原子的格局立异数组里的整型,其常用艺术如下

  • int addAndGet(int i, int
    deltaState of Qatar:以原子方式将输入值与数组中索引i的要素相加。
  • boolean compareAndSet(int i, int expect, int
    updateState of Qatar:要是当前值等于预期值,则以原子方式将数组地方i的因素设置成update值。

实例代码如下:

public class AtomicIntegerArrayTest {

    static int[] value = new int[] { 1, 2 };

    static AtomicIntegerArray ai = new AtomicIntegerArray(value);

    public static void main(String[] args) {
        ai.getAndSet(0, 3);
        System.out.println(ai.get(0));
        System.out.println(value[0]);
    }

}

输出

3
1

AtomicIntegerArray类要求留意的是,数组value通过布局方法传递步入,然后AtomicIntegerArray会将日前数组复制一份,所以当AtomicIntegerArray对个中的数组成分举办改进时,不会耳熟能详到传播的数组。

原子更新引用类型

原子更新为主类型的AtomicInteger,只可以更新二个变量,如若要原子的翻新多个变量,就要求动用那一个原子更新引用类型提供的类。Atomic包提供了以下多个类:

  • AtomicReference:原子更新援引类型。
  • AtomicReferenceFieldUpdater:原子更新援引类型里的字段。
  • AtomicMarkableReference:原子更新带有标识位的援用类型。可以原子的立异三个布尔类型的标志位和引用类型。布局方法是AtomicMarkableReference(V
    initialRef, boolean initialMark卡塔尔(قطر‎

AtomicReference的利用例子代码如下:

public class AtomicReferenceTest {

    public static AtomicReference<user> atomicUserRef = new AtomicReference<user>();

    public static void main(String[] args) {
        User user = new User("conan", 15);
        atomicUserRef.set(user);
        User updateUser = new User("Shinichi", 17);
        atomicUserRef.compareAndSet(user, updateUser);
        System.out.println(atomicUserRef.get().getName());
        System.out.println(atomicUserRef.get().getOld());
    }

    static class User {
        private String name;
        private int old;

        public User(String name, int old) {
            this.name = name;
            this.old = old;
        }

        public String getName() {
            return name;
        }

        public int getOld() {
            return old;
        }
    }
}

输出

Shinichi
17

原子更新字段类

举例大家只必要有些类里的某些字段,那么就必要运用原子更新字段类,Atomic包提供了以下多少个类:

  • AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。
  • AtomicLongFieldUpdater:原子更新长整型字段的更新器。
  • AtomicStampedReference:原子更新带有版本号的援用类型。该类将整数值与引用关联起来,可用于原子的更数据和数码的版本号,能够解决选拔CAS实行原子更新时,或许现身的ABA难题。

原子更新字段类都是抽象类,每一趟使用都时候必需采纳静态方法newUpdater创设一个更新器。原子更新类的字段的必需利用public
volatile修饰符。AtomicIntegerFieldUpdater的例子代码如下:

public class AtomicIntegerFieldUpdaterTest {

    private static AtomicIntegerFieldUpdater<User> a = AtomicIntegerFieldUpdater
            .newUpdater(User.class, "old");

    public static void main(String[] args) {
        User conan = new User("conan", 10);
        System.out.println(a.getAndIncrement(conan));
        System.out.println(a.get(conan));
    }

    public static class User {
        private String name;
        public volatile int old;

        public User(String name, int old) {
            this.name = name;
            this.old = old;
        }

        public String getName() {
            return name;
        }

        public int getOld() {
            return old;
        }
    }
}

输出

10
11

转发自并发编制程序网 – ifeve.com本文链接地址:
Java中的Atomic包使用指南

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图