当前位置:   article > 正文

【JUC并发】4. atomic包各类原理详解,不容错过

atomic包

目录

一、简介

二、类详解

1. AtomicBoolean

2. AtomicInteger

3. AtomicLong

4. AtomicReference

5. AtomicStampedReference

6. AtomicMarkableReference

三、总结


一、简介

java.util.concurrent.atomic 包提供了一些基于CAS(Compare-and-Swap)算法的原子操作类,用于在多线程环境下进行原子操作,避免了使用 synchronized 等锁机制的开销和复杂性。以下是该包中一些常用的类及其实现原理。

二、类详解

1. AtomicBoolean

AtomicBoolean 用于在多线程环境下对一个布尔类型的变量进行原子操作。它的实现原理是使用一个 volatile 修饰的 int 类型变量来表示布尔值,其中 1 表示 true0 表示 false。它的操作方法包括 get()set()compareAndSet() 等。

  1. public class AtomicBooleanDemo {
  2. private static AtomicBoolean flag = new AtomicBoolean(false);
  3. public static void main(String[] args) throws InterruptedException {
  4. Thread t1 = new Thread(() -> {
  5. while (!flag.compareAndSet(false, true)) {
  6. // do something
  7. }
  8. System.out.println("Thread 1 get the lock.");
  9. try {
  10. Thread.sleep(5000);
  11. } catch (InterruptedException e) {
  12. e.printStackTrace();
  13. }
  14. flag.set(false);
  15. System.out.println("Thread 1 release the lock.");
  16. });
  17. Thread t2 = new Thread(() -> {
  18. while (!flag.compareAndSet(false, true)) {
  19. // do something
  20. }
  21. System.out.println("Thread 2 get the lock.");
  22. try {
  23. Thread.sleep(3000);
  24. } catch (InterruptedException e) {
  25. e.printStackTrace();
  26. }
  27. flag.set(false);
  28. System.out.println("Thread 2 release the lock.");
  29. });
  30. t1.start();
  31. t2.start();
  32. t1.join();
  33. t2.join();
  34. }
  35. }

2. AtomicInteger

AtomicInteger 用于在多线程环境下对一个整型变量进行原子操作。它的实现原理与 AtomicBoolean 类似,使用一个 volatile 修饰的 int 类型变量来表示整数值,同时使用 CAS 算法保证原子性。它的操作方法包括 get()set()getAndIncrement()compareAndSet() 等。

  1. public class AtomicIntegerDemo {
  2. private static AtomicInteger counter = new AtomicInteger(0);
  3. public static void main(String[] args) throws InterruptedException {
  4. Thread t1 = new Thread(() -> {
  5. for (int i = 0; i < 10000; i++) {
  6. counter.incrementAndGet();
  7. }
  8. });
  9. Thread t2 = new Thread(() -> {
  10. for (int i = 0; i < 10000; i++) {
  11. counter.incrementAndGet();
  12. }
  13. });
  14. t1.start();
  15. t2.start();
  16. t1.join();
  17. t2.join();
  18. System.out.println("Counter: " + counter.get());
  19. }
  20. }

3. AtomicLong

AtomicLong 用于在多线程环境下对一个长整型变量进行原子操作。它的实现原理与 AtomicInteger 类似,使用一个 volatile 修饰的 long 类型变量来表示长整数值,同时使用 CAS 算法保证原子性。它的操作方法与 AtomicInteger 类似。

  1. public class AtomicLongDemo {
  2. private static AtomicLong counter = new AtomicLong(0L);
  3. public static void main(String[] args) throws InterruptedException {
  4. Thread t1 = new Thread(() -> {
  5. for (int i = 0; i < 10000000; i++) {
  6. counter.incrementAndGet();
  7. }
  8. });
  9. Thread t2 = new Thread(() -> {
  10. for (int i = 0; i < 10000000; i++) {
  11. counter.incrementAndGet();
  12. }
  13. });
  14. t1.start();
  15. t2.start();
  16. t1.join();
  17. t2.join();
  18. System.out.println("Counter: " + counter.get());
  19. }
  20. }

4. AtomicReference

AtomicReference 用于在多线程环境下对一个对象类型的变量进行原子操作。它的实现原理是使用 volatile 修饰的 Object 类型变量来表示对象引用,同时使用 CAS 算法保证原子性。它的操作方法包括 get()set()compareAndSet() 等。

  1. public class AtomicReferenceDemo {
  2. private static AtomicReference<String> ref = new AtomicReference<>("Hello");
  3. public static void main(String[] args) throws InterruptedException {
  4. Thread t1 = new Thread(() -> {
  5. ref.compareAndSet("Hello", "World");
  6. });
  7. Thread t2 = new Thread(() -> {
  8. ref.compareAndSet("Hello", "Java");
  9. });
  10. t1.start();
  11. t2.start();
  12. t1.join();
  13. t2.join();
  14. System.out.println("Reference: " + ref.get());
  15. }
  16. }

5. AtomicStampedReference

AtomicStampedReference 通过维护一个时间戳(stamp)来解决ABA问题。在每次更新时,除了更新值以外还要更新时间戳。因此,即使值相同,时间戳也不同,从而避免了ABA问题。当然,这也要求每次更新时时间戳必须不同。

  1. AtomicStampedReference<String> ref = new AtomicStampedReference<>("initial value", 0);
  2. int currentStamp = ref.getStamp();
  3. String currentValue = ref.getReference();
  4. boolean success = ref.compareAndSet(currentValue, "new value", currentStamp, currentStamp + 1);

6. AtomicMarkableReference

AtomicMarkableReference 通过维护一个标记(mark)来解决ABA问题。在每次更新时,除了更新值以外还要更新标记。因此,即使值相同,标记也不同,从而避免了ABA问题。当然,这也要求每次更新时标记必须不同。

以下是 AtomicMarkableReference 的一个示例:

  1. AtomicMarkableReference<String> ref = new AtomicMarkableReference<>("initial value", false);
  2. boolean currentMark = ref.isMarked();
  3. String currentValue = ref.getReference();
  4. boolean success = ref.compareAndSet(currentValue, "new value", currentMark, !currentMark);

三、总结

  • java.util.concurrent.atomic 包提供了一些基于 CAS 算法的原子操作类,用于在多线程环境下进行原子操作。这些类的实现原理都是使用 volatile 修饰的基本类型变量或对象引用变量,同时使用 CAS 算法保证原子性。在使用这些原子操作类时,需要注意它们的线程安全性和使用方式。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/996122
推荐阅读
相关标签
  

闽ICP备14008679号