原子操作类介绍

本文详细介绍了Java中用于解决多线程环境下变量操作原子性问题的原子操作类。包括AtomicBoolean、AtomicInteger等原子更新基本类型,AtomicIntegerArray等原子更新数组类型,以及AtomicReference等原子更新引用类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原子操作类介绍

因为java的多线程的缘故,当多个线程同时修改同一个变量,导致最后变量得不到预期的结果。原因是多线程操作,导致变量操作缺少原子性,所以导致变量在多线程的操作下达不到预期效果。

如下面案例所示:

public class Test {

    private static int count = 10;
    private static AtomicInteger atomicCount = new AtomicInteger(10);
    private static final ExecutorService executorService = Executors.newFixedThreadPool(4);

    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    atomicExecute();
//                    unAtomicExecute();
                }
            });
        }
    }

    private static void unAtomicExecute() {
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.print(--count+" ");
    }

    private static void atomicExecute() {
        try {
            Thread.sleep(50);//使得效果更明显
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.print( atomicCount.decrementAndGet()+" ");
    }
}


unAtomicExecute()方法执行的结果为:9 9 8 9 7 5 4 6 3 2 

atomicExecute()方法执行的结果为:9 6 8 7 5 2 4 3 1 0 

从打印的结果看出,unAtomicExecute()出现重复的数字,证明其对数字的操作是不具有原子性的。atomicExecute()使用的是AtomicInteger是具有原子性的。

JavaJDK1.5提供了java.util.concurrent.atomic包(简称Atomic包),这个包中的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式。

Atomic包提供4种类型的原子类。

  • 原子更新基本类型

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

    AtomicBooleanAtomicIntegerAtomicLong的实现相差无几,这里通过AtomicInteger常用API来介绍。

    • AtomicInteger的构造

      public AtomicInteger(int var1) {//传入 初始值
          this.value = var1;
      }
      
      public AtomicInteger() {//默认初始值
      }
    • 常用方法

      public final int get() {//获取当前值
          return this.value;
      }
      
      public final void set(int var1) {//设置值
          this.value = var1;
      }
      
      public final int getAndIncrement() {//先获取当前值后在自增1
          return unsafe.getAndAddInt(this, valueOffset, 1);
      }
      
      public final int getAndDecrement() {////先获取当前值后在加自减1
          return unsafe.getAndAddInt(this, valueOffset, -1);
      }
      
      public final int getAndAdd(int var1) {//先获取当前值后再加上传入参数的值
          return unsafe.getAndAddInt(this, valueOffset, var1);
      }
      
      public final int incrementAndGet() {//先自增1,再获取当前值
          return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
      }
      
      public final int decrementAndGet() {//先自减1,再获取当前值
          return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
      }
      
      public final int addAndGet(int var1) {//先加上传入参数的值,再获取当前值
          return unsafe.getAndAddInt(this, valueOffset, var1) + var1;
      }
      
  • 原子更新数组

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

    在java中,提供了许多好用的防并发的容器,所以上面提到的一般都不常用。

  • 原子更新引用

    AtomicReference:原子更新引用类型
    
    AtomicReferenceFieldUpdater:原子更新引用类型里的字段
    
    AtomicMarkableReference:原子更新带有标记位的引用类型

    这3个类的实现方法基本一样,这里就以AtomicReference写一个示例。

    public class AtomicReferenceTest {       
    
        public static AtomicReference<user> atomicUserRef = new AtomicReference<user>();   
    
        public static void main(String[] args) {         
            User user = new User("lisi", 16);
            atomicUserRef.set(user);
            System.out.println(atomicUserRef.get().getName() + "  " + atomicUserRef.get().getOld());
    
            System.out.println("-------------------------");
    
            User updateUser = new User("zhangsan", 18);
            atomicUserRef.compareAndSet(user, updateUser);
            System.out.println(atomicUserRef.get().getName() + "  " + 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;
            }        
        } 
    }
    
    
    打印结果:
    
    
    lisi  16
    -------------------------
    
    zhangsan  18
  • 原子更新属性

    AtomicIntegerFieldUpdater:原子更新整型的字段的更新器
    
    AtomicLongFieldUpdater:原子更新长整型字段的更新器
    
    AtomicStampedReference:原子更新带有版本号的引用类型

    这几个类用的用的比较少,使用方法和上面的类似,类也不复杂,有兴趣可以了解下源码,这里就不写例子了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值