<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【Java】原子類(lèi)

          共 30326字,需瀏覽 61分鐘

           ·

          2023-01-07 04:05

          點(diǎn)擊關(guān)注,與你共同成長(zhǎng)!




          【Java】原子類(lèi)

          前言

          保證線程安全是 Java 并發(fā)編程必須要解決的重要問(wèn)題。Java 從原子性可見(jiàn)性有序性這三大特性入手,確保多線程的數(shù)據(jù)一致性。

          • 確保線程安全最常見(jiàn)的做法是利用鎖機(jī)制(Locksychronized)來(lái)對(duì)共享數(shù)據(jù)做互斥同步,這樣在同一個(gè)時(shí)刻,只有一個(gè)線程可以執(zhí)行某個(gè)方法或者某個(gè)代碼塊,那么操作必然是原子性的,線程安全的。互斥同步最主要的問(wèn)題是線程阻塞和喚醒所帶來(lái)的性能問(wèn)題;
          • volatile 是輕量級(jí)的鎖(自然比普通鎖性能要好),它保證了共享變量在多線程中的可見(jiàn)性,但無(wú)法保證原子性。所以,它只能在一些特定場(chǎng)景下使用;
          • 為了兼顧原子性以及鎖帶來(lái)的性能問(wèn)題,Java 引入了 CAS (主要體現(xiàn)在 Unsafe 類(lèi))來(lái)實(shí)現(xiàn)非阻塞同步(也叫樂(lè)觀鎖),并基于 CAS ,提供了一套原子工具類(lèi)

          原子類(lèi)

          原子變量類(lèi) 比鎖的粒度更細(xì),更輕量級(jí),并且對(duì)于在多處理器系統(tǒng)上實(shí)現(xiàn)高性能的并發(fā)代碼來(lái)說(shuō)是非常關(guān)鍵的。原子變量將發(fā)生競(jìng)爭(zhēng)的范圍縮小到單個(gè)變量上

          原子變量類(lèi)可以分為 4 類(lèi)

          • 基本類(lèi)型
            • AtomicBoolean:布爾類(lèi)型原子類(lèi);
            • AtomicInteger:整型原子類(lèi);
            • AtomicLong:長(zhǎng)整型原子類(lèi)。
          • 引用類(lèi)型
            • AtomicReference:引用類(lèi)型原子類(lèi);
            • AtomicMarkableReference:帶有標(biāo)記位的引用類(lèi)型原子類(lèi);
            • AtomicStampedReference:帶有版本號(hào)的引用類(lèi)型原子類(lèi)。
          • 數(shù)組類(lèi)型
            • AtomicIntegerArray:整形數(shù)組原子類(lèi);
            • AtomicLongArray:長(zhǎng)整型數(shù)組原子類(lèi);
            • AtomicReferenceArray:引用類(lèi)型數(shù)組原子類(lèi)。
          • 屬性更新器類(lèi)型
            • AtomicIntegerFieldUpdater:整型字段的原子更新器;
            • AtomicLongFieldUpdater:長(zhǎng)整型字段的原子更新器;
            • AtomicReferenceFieldUpdater:原子更新引用類(lèi)型里的字段。

          基本類(lèi)型

          • AtomicBoolean:布爾類(lèi)型原子類(lèi);
          • AtomicInteger:整型原子類(lèi);
          • AtomicLong:長(zhǎng)整型原子類(lèi)。

          線程不安全

          package cn.com.codingce.juc.atomic;

          import java.util.concurrent.ExecutorService;
          import java.util.concurrent.Executors;
          import java.util.concurrent.atomic.AtomicInteger;

          public class AtomicIntegerExample {
              
              static int value2 = 0;

              public static void main(String[] args) {
                  System.out.println("==============ordinaryMethod==============");
                  ExecutorService executor3 = Executors.newFixedThreadPool(5);
                  for (int i = 0; i < 10; i++) {
                      executor3.execute(()->{
                          System.out.println(Thread.currentThread().getName() + ", value2: " + value2 + " ");
                          value2++;
                      });
                  }
                  executor3.shutdown();
              }

          }

          output

          ==============Method==============
          pool-1-thread-3, value2: 0 
          pool-1-thread-2, value2: 0 
          pool-1-thread-3, value2: 2 
          pool-1-thread-4, value2: 0 
          pool-1-thread-1, value2: 0 
          pool-1-thread-3, value2: 3 
          pool-1-thread-2, value2: 2 
          pool-1-thread-5, value2: 1 
          pool-1-thread-4, value2: 5 
          pool-1-thread-1, value2: 5 

          synchronized案例

          package cn.com.codingce.juc.atomic;

          import java.util.concurrent.ExecutorService;
          import java.util.concurrent.Executors;
          import java.util.concurrent.atomic.AtomicInteger;

          public class AtomicIntegerExample {

              static int value1 = 0;

              public static void main(String[] args) {
                  System.out.println("==============synchronizedMethod==============");
                  ExecutorService executor2 = Executors.newFixedThreadPool(5);
                  for (int i = 0; i < 10; i++) {
                      executor2.execute(AtomicIntegerExample::synchronizedMethod);
                  }
                  executor2.shutdown();
              }

              public static synchronized void synchronizedMethod() {
                  System.out.println(Thread.currentThread().getName() + ", value1: " + value1 + " ");
                  value1++;
              }

          }

          output

          ==============synchronizedMethod==============
          pool-1-thread-1, value1: 0 
          pool-1-thread-3, value1: 1 
          pool-1-thread-2, value1: 2 
          pool-1-thread-1, value1: 3 
          pool-1-thread-4, value1: 4 
          pool-1-thread-3, value1: 5 
          pool-1-thread-4, value1: 6 
          pool-1-thread-1, value1: 7 
          pool-1-thread-5, value1: 8 
          pool-1-thread-2, value1: 9

          AtomicInteger 案例

          package cn.com.codingce.juc.atomic;

          import java.util.concurrent.ExecutorService;
          import java.util.concurrent.Executors;
          import java.util.concurrent.atomic.AtomicInteger;

          public class AtomicIntegerExample {

              static AtomicInteger value = new AtomicInteger(0);

              public static void main(String[] args) {
                  System.out.println("==============AtomicInteger==============");
                  ExecutorService executor = Executors.newFixedThreadPool(5);
                  for (int i = 0; i < 10; i++) {
                      executor.execute(AtomicIntegerExample::atomicIntegerMethod);
                  }
                  executor.shutdown();
              }

              public static synchronized void atomicIntegerMethod() {
                  System.out.println(Thread.currentThread().getName() + ", value: " + value.get() + " ");
                  value.incrementAndGet();
              }

          }

          output

          ==============AtomicInteger==============
          pool-1-thread-2, value: 0 
          pool-1-thread-1, value: 1 
          pool-1-thread-3, value: 2 
          pool-1-thread-5, value: 3 
          pool-1-thread-1, value: 4 
          pool-1-thread-2, value: 5 
          pool-1-thread-4, value: 6 
          pool-1-thread-1, value: 7 
          pool-1-thread-5, value: 8 
          pool-1-thread-3, value: 9

          AtomicInteger實(shí)現(xiàn)可以看到如下定義

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

          static {
              try {
                  valueOffset = unsafe.objectFieldOffset
                      (AtomicInteger.class.getDeclaredField("value"));
              } catch (Exception ex) { throw new Error(ex); }
          }

          private volatile int value;
          • value - value 屬性使用 volatile 修飾,使得對(duì) value 的修改在并發(fā)環(huán)境下對(duì)所有線程可見(jiàn);
          • valueOffset - value 屬性的偏移量,通過(guò)這個(gè)偏移量可以快速定位到 value 字段,這個(gè)是實(shí)現(xiàn) AtomicInteger 的關(guān)鍵;
          • unsafe - Unsafe 類(lèi)型的屬性,它為 AtomicInteger 提供了 CAS 操作。

          引用類(lèi)型

          Java 數(shù)據(jù)類(lèi)型分為 基本數(shù)據(jù)類(lèi)型引用數(shù)據(jù)類(lèi)型 兩大類(lèi)。

          • AtomicReference:引用類(lèi)型原子類(lèi);
          • AtomicMarkableReference:帶有標(biāo)記位的引用類(lèi)型原子類(lèi);
          • AtomicStampedReference:帶有版本號(hào)的引用類(lèi)型原子類(lèi)。

          AtomicStampedReference 類(lèi)在引用類(lèi)型原子類(lèi)中,徹底地解決了 ABA 問(wèn)題,其它的 CAS 能力與另外兩個(gè)類(lèi)相近,所以最具代表性。

          基于 AtomicReference 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的自旋鎖

          package cn.com.codingce.juc.atomic;

          import java.util.concurrent.ExecutorService;
          import java.util.concurrent.Executors;
          import java.util.concurrent.atomic.AtomicReference;

          public class AtomicReferenceExample {
              public static int ticket = 10;

              public static void main(String[] args) {
                  threadSafe();
              }

              private static void threadSafe() {
                  SpinLock lock = new SpinLock();
                  ExecutorService executorService = Executors.newFixedThreadPool(3);
                  for (int i = 0; i < 5; i++) {
                      executorService.execute(new MyThread(lock));
                  }
                  executorService.shutdown();
              }

              /**
               * 基于 {@link AtomicReference} 實(shí)現(xiàn)的簡(jiǎn)單自旋鎖
               */

              static class SpinLock {
                  private AtomicReference<Thread> atomicReference = new AtomicReference<>();

                  public void lock() {
                      Thread current = Thread.currentThread();
                      while (!atomicReference.compareAndSet(null, current)) ;
                  }

                  public void unlock() {
                      Thread current = Thread.currentThread();
                      while (!atomicReference.compareAndSet(current, null)) ;
                  }
              }

              static class MyThread implements Runnable {

                  private SpinLock lock;

                  public MyThread(SpinLock lock) {
                      this.lock = lock;
                  }

                  @Override
                  public void run() {
                      while (ticket > 0) {
                          lock.lock();
                          if (ticket > 0) {
                              System.out.println(Thread.currentThread().getName() + " 賣(mài)出了第 " + ticket + " 張票");
                              ticket--;
                          }
                          lock.unlock();
                      }
                  }
              }
          }

          output

          pool-1-thread-1 賣(mài)出了第 10 張票
          pool-1-thread-3 賣(mài)出了第 9 張票
          pool-1-thread-2 賣(mài)出了第 8 張票
          pool-1-thread-1 賣(mài)出了第 7 張票
          pool-1-thread-2 賣(mài)出了第 6 張票
          pool-1-thread-1 賣(mài)出了第 5 張票
          pool-1-thread-3 賣(mài)出了第 4 張票
          pool-1-thread-1 賣(mài)出了第 3 張票
          pool-1-thread-2 賣(mài)出了第 2 張票
          pool-1-thread-1 賣(mài)出了第 1 張票

          原子類(lèi)的實(shí)現(xiàn)基于 CAS 機(jī)制,而 CAS 存在 ABA 問(wèn)題,為了解決 ABA 問(wèn)題,才有了 AtomicMarkableReferenceAtomicStampedReference

          AtomicMarkableReference 使用一個(gè)布爾值作為標(biāo)記,修改時(shí)在 true / false 之間切換。這種策略不能根本上解決 ABA 問(wèn)題,但是可以降低 ABA 發(fā)生的幾率。常用于緩存或者狀態(tài)描述這樣的場(chǎng)景。

          package cn.com.codingce.juc.atomic;

          import java.util.concurrent.ExecutorService;
          import java.util.concurrent.Executors;
          import java.util.concurrent.TimeUnit;
          import java.util.concurrent.atomic.AtomicMarkableReference;

          public class AtomicMarkableReferenceExample {

              private final static String INIT_STR = "后端碼匠";

              public static void main(String[] args) throws InterruptedException {

                  final AtomicMarkableReference<String> amr = new AtomicMarkableReference<>(INIT_STR, false);

                  ExecutorService executorService = Executors.newFixedThreadPool(3);
                  for (int i = 0; i < 3; i++) {
                      executorService.execute(() -> {
                          System.out.println("當(dāng)前線程: " + Thread.currentThread().getName());
                          try {
                              Thread.sleep(Math.abs((int) (Math.random() * 100)));
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }

                          String name = Thread.currentThread().getName();
                          if (amr.compareAndSet(INIT_STR, name, amr.isMarked(), !amr.isMarked())) {
                              System.out.println(Thread.currentThread().getName() + " 修改了對(duì)象!");
                              System.out.println("新的對(duì)象為:" + amr.getReference());
                          }
                      });
                  }

                  executorService.shutdown();
                  System.out.println(executorService.awaitTermination(3, TimeUnit.SECONDS));
                  ;
              }
          }

          output

          當(dāng)前線程: pool-1-thread-1
          當(dāng)前線程: pool-1-thread-3
          當(dāng)前線程: pool-1-thread-2
          pool-1-thread-3 修改了對(duì)象!
          新的對(duì)象為:pool-1-thread-3
          true

          AtomicStampedReference 使用一個(gè)整型值做為版本號(hào),每次更新前先比較版本號(hào),如果一致,才進(jìn)行修改。通過(guò)這種策略,可以根本上解決 ABA 問(wèn)題。

          package cn.com.codingce.juc.atomic;

          import java.util.concurrent.ExecutorService;
          import java.util.concurrent.Executors;
          import java.util.concurrent.TimeUnit;
          import java.util.concurrent.atomic.AtomicStampedReference;

          public class AtomicStampedReferenceExample {

              private final static String INIT_REF = "后端碼匠";
              private final static AtomicStampedReference<String> asr = new AtomicStampedReference<>(INIT_REF, 0);

              public static void main(String[] args) throws InterruptedException {

                  System.out.println("初始對(duì)象為:" + asr.getReference());
                  ExecutorService executorService = Executors.newFixedThreadPool(3);
                  for (int i = 0; i < 3; i++) {
                      executorService.execute(() -> {
                          System.out.println("當(dāng)前線程: " + Thread.currentThread().getName());
                          try {
                              Thread.sleep(Math.abs((int) (Math.random() * 100)));
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }

                          final int stamp = asr.getStamp();
                          if (asr.compareAndSet(INIT_REF, Thread.currentThread().getName(), stamp, stamp + 1)) {
                              System.out.println(Thread.currentThread().getName() + " 修改了對(duì)象!");
                              System.out.println("新的對(duì)象為:" + asr.getReference());
                          }
                      });
                  }

                  executorService.shutdown();
                  System.out.println(executorService.awaitTermination(3, TimeUnit.SECONDS));
              }

          }

          output

          初始對(duì)象為:后端碼匠
          當(dāng)前線程: pool-1-thread-1
          當(dāng)前線程: pool-1-thread-2
          當(dāng)前線程: pool-1-thread-3
          pool-1-thread-2 修改了對(duì)象!
          新的對(duì)象為:pool-1-thread-2
          true

          數(shù)組類(lèi)型

          • AtomicIntegerArray:整形數(shù)組原子類(lèi);
          • AtomicLongArray:長(zhǎng)整型數(shù)組原子類(lèi);
          • AtomicReferenceArray:引用類(lèi)型數(shù)組原子類(lèi)。

          AtomicIntegerArray示例

          package cn.com.codingce.juc.atomic;

          import java.util.concurrent.atomic.AtomicIntegerArray;

          public class AtomicIntegerArrayExample {

              private static AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(10);

              public static void main(final String[] arguments) throws InterruptedException {
                  System.out.println("Init Values: ");
                  for (int i = 0; i < atomicIntegerArray.length(); i++) {
                      atomicIntegerArray.set(i, i);
                      System.out.print(atomicIntegerArray.get(i) + " ");
                  }
                  System.out.println();
                  System.out.println("========================================");
                  Thread t1 = new Thread(new Increment());
                  Thread t2 = new Thread(new Compare());
                  t1.start();
                  t2.start();

                  t1.join();
                  t2.join();

                  System.out.println("Final Values: ");
                  for (int i = 0; i < atomicIntegerArray.length(); i++) {
                      System.out.print(atomicIntegerArray.get(i) + " ");
                  }
                  System.out.println();
              }

              static class Increment implements Runnable {
                  @Override
                  public void run() {
                      for (int i = 0; i < atomicIntegerArray.length(); i++) {
                          int value = atomicIntegerArray.incrementAndGet(i);
                          System.out.println(Thread.currentThread().getName() + ", index = " + i + ", value = " + value);
                      }
                  }
              }

              static class Compare implements Runnable {
                  @Override
                  public void run() {
                      for (int i = 0; i < atomicIntegerArray.length(); i++) {
                          boolean swapped = atomicIntegerArray.compareAndSet(i, 1100);
                          if (swapped) {
                              System.out.println(Thread.currentThread().getName() + " swapped, index = " + i + ", value = 3");
                          }
                      }
                  }
              }

          }

          output

          Init Values: 
          0 1 2 3 4 5 6 7 8 9 
          ========================================
          Thread-0, index = 0, value = 1
          Thread-0, index = 1, value = 2
          Thread-1 swapped, index = 0, value = 3
          Thread-0, index = 2, value = 3
          Thread-0, index = 3, value = 4
          Thread-0, index = 4, value = 5
          Thread-0, index = 5, value = 6
          Thread-0, index = 6, value = 7
          Thread-0, index = 7, value = 8
          Thread-0, index = 8, value = 9
          Thread-0, index = 9, value = 10
          Final Values: 
          100 2 3 4 5 6 7 8 9 10 

          屬性更新器類(lèi)型

          更新器類(lèi)支持基于反射機(jī)制的更新字段值的原子操作。

          • AtomicIntegerFieldUpdater:整型字段的原子更新器。
          • AtomicLongFieldUpdater:長(zhǎng)整型字段的原子更新器。
          • AtomicReferenceFieldUpdater:原子更新引用類(lèi)型里的字段。

          這些類(lèi)的使用有一定限制:

          • 因?yàn)閷?duì)象的屬性修改類(lèi)型原子類(lèi)都是抽象類(lèi),所以每次使用都必須使用靜態(tài)方法 newUpdater() 創(chuàng)建一個(gè)更新器,并且需要設(shè)置想要更新的類(lèi)和屬性;
          • 字段必須是 volatile 類(lèi)型的;
          • 不能作用于靜態(tài)變量(static);
          • 不能作用于常量(final)。
          package cn.com.codingce.juc.atomic;

          import java.util.concurrent.ExecutorService;
          import java.util.concurrent.Executors;
          import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

          public class AtomicReferenceFieldUpdaterExample {

              static User user = new User("歡迎關(guān)注");

              static AtomicReferenceFieldUpdater<User, String> updater = AtomicReferenceFieldUpdater.newUpdater(User.classString.class, "name");

              public static void main(String[] args) {
                  ExecutorService executorService = Executors.newFixedThreadPool(3);
                  for (int i = 0; i < 5; i++) {
                      executorService.execute(new MyThread());
                  }
                  executorService.shutdown();
              }

              static class MyThread implements Runnable {

                  @Override
                  public void run() {
                      if (updater.compareAndSet(user, "歡迎關(guān)注""后端碼匠")) {
                          try {
                              Thread.sleep(1000);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          System.out.println(Thread.currentThread().getName() + " 已修改 name = " + user.getName());
                      } else {
                          System.out.println(Thread.currentThread().getName() + " 已被其他線程修改");
                      }
                  }

              }

              static class User {
                  volatile String name;

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

                  public String getName() {
                      return name;
                  }

                  public User setName(String name) {
                      this.name = name;
                      return this;
                  }

              }
          }

          output

          pool-1-thread-2 已被其他線程修改
          pool-1-thread-3 已被其他線程修改
          pool-1-thread-2 已被其他線程修改
          pool-1-thread-3 已被其他線程修改
          pool-1-thread-1 已修改 name = 后端碼匠

          方案對(duì)比

          Atomic|synchronized

          1、背后原理的不同

          原子類(lèi):它保證線程安全的原理是利用了 CAS 操作。從這一點(diǎn)上看,雖然原子類(lèi)和 synchronized 都能保證線程安全,但是其實(shí)現(xiàn)原理是大有不同的;

          synchronized:背后的 monitor 鎖,也就是 synchronized 原理,同步方法和同步代碼塊的背后原理會(huì)有少許差異,但總體思想是一致的:在執(zhí)行同步代碼之前,需要首先獲取到 monitor 鎖,執(zhí)行完畢后,再釋放鎖。2、使用范圍的不同

          原子類(lèi):它的使用范圍是比較局限的。因?yàn)橐粋€(gè)原子類(lèi)僅僅是一個(gè)對(duì)象,不夠靈活;

          synchronized 它的使用范圍要廣泛得多。比如說(shuō) synchronized 既可以修飾一個(gè)方法,又可以修飾一段代碼,相當(dāng)于可以根據(jù)我們的需要,非常靈活地去控制它的應(yīng)用范圍;

          所以?xún)H有少量的場(chǎng)景,例如計(jì)數(shù)器等場(chǎng)景,可以使用原子類(lèi)。而在其他更多的場(chǎng)景下,如果原子類(lèi)不適用,那么就可以考慮用 synchronized 來(lái)解決這個(gè)問(wèn)題。

          3、粒度的區(qū)別

          原子類(lèi):原子變量的粒度是比較小的,它可以把競(jìng)爭(zhēng)范圍縮小到變量級(jí)別;

          synchronized:通常情況下,synchronized 鎖的粒度都要大于原子變量的粒度;

          如果只把一行代碼用 synchronized 給保護(hù)起來(lái)的話(huà),有一點(diǎn)殺雞焉用牛刀的感覺(jué)。

          4、性能的區(qū)別,同時(shí)也是悲觀鎖和樂(lè)觀鎖的區(qū)別

          因?yàn)?synchronized 是一種典型的悲觀鎖,而原子類(lèi)恰恰相反,它利用的是樂(lè)觀鎖。所以,在比較 synchronized 和 AtomicInteger 的時(shí)候,其實(shí)也就相當(dāng)于比較了悲觀鎖和樂(lè)觀鎖的區(qū)別;

          從性能上來(lái)考慮的話(huà),悲觀鎖的操作相對(duì)來(lái)講是比較重量級(jí)的。因?yàn)?synchronized 在競(jìng)爭(zhēng)激烈的情況下,會(huì)讓拿不到鎖的線程阻塞,而原子類(lèi)是永遠(yuǎn)不會(huì)讓線程阻塞的。不過(guò),雖然 synchronized 會(huì)讓線程阻塞,但是這并不代表它的性能就比原子類(lèi)差

          悲觀鎖的開(kāi)銷(xiāo)是固定的,也是一勞永逸的。隨著時(shí)間的增加,這種開(kāi)銷(xiāo)并不會(huì)線性增長(zhǎng),而樂(lè)觀鎖雖然在短期內(nèi)的開(kāi)銷(xiāo)不大,但是隨著時(shí)間的增加,它的開(kāi)銷(xiāo)也是逐步上漲的

          所以從性能的角度考慮,它們沒(méi)有一個(gè)孰優(yōu)孰劣的關(guān)系,而是要區(qū)分具體的使用場(chǎng)景。在競(jìng)爭(zhēng)非常激烈的情況下,推薦使用 synchronized;而在競(jìng)爭(zhēng)不激烈的情況下,使用原子類(lèi)會(huì)得到更好的效果

          注意

          synchronized 的性能隨著 JDK 的升級(jí),也得到了不斷的優(yōu)化。synchronized 會(huì)從無(wú)鎖升級(jí)到偏向鎖,再升級(jí)到輕量級(jí)鎖,最后才會(huì)升級(jí)到讓線程阻塞的重量級(jí)鎖。因此synchronized 在競(jìng)爭(zhēng)不激烈的情況下,性能也是不錯(cuò)的,不需要“談鎖色變”。

          Unsafe類(lèi)

          實(shí)際上Atomic包里的類(lèi)基本都是使用Unsafe實(shí)現(xiàn)的包裝類(lèi)。也就是上面的原子類(lèi)實(shí)現(xiàn)過(guò)程中都會(huì)用到Unsafe類(lèi)。Java中的Unsafe類(lèi)提供了類(lèi)似C++手動(dòng)管理內(nèi)存的能力。Unsafe類(lèi),全限定名是sun.misc.Unsafe,從名字可以看出來(lái)這個(gè)類(lèi)對(duì)普通程序員來(lái)說(shuō)是“危險(xiǎn)”的,一般應(yīng)用開(kāi)發(fā)者不會(huì)用到這個(gè)類(lèi)。Unsafe類(lèi)是"final"的,不允許繼承。且構(gòu)造函數(shù)是private的,無(wú)法在外部對(duì)其進(jìn)行實(shí)例化。

          Unsafe的典型應(yīng)用

          • 堆外內(nèi)存操作。DirectByteBuffer是Java用于實(shí)現(xiàn)堆外內(nèi)存的一個(gè)重要類(lèi),通常用在通信過(guò)程中做緩沖池,如在Netty、MINA等NIO框架中應(yīng)用廣泛;DirectByteBuffer對(duì)于堆外內(nèi)存的創(chuàng)建、 使用、銷(xiāo)毀等邏輯均由Unsafe提供的堆外內(nèi)存API來(lái)實(shí)現(xiàn);
          • ReentrantLock、Atomic等API通過(guò)CAS修改state等等,底層用的也是Unsafe;
          • 線程調(diào)度:如LockSupport.park()和LockSupport.unpark()實(shí)現(xiàn)線程的阻塞和喚醒。而 LockSupport的park、unpark方法實(shí)際是調(diào)用Unsafe的park、unpark方式來(lái)實(shí)現(xiàn);
          • 內(nèi)存屏障,通過(guò)Unsafe的loadFence方法加入一個(gè)內(nèi)存屏障,目的是避免指令重排。



          【Java】線程池梳理

          【C++】const關(guān)鍵字


          以上,便是今天的分享,希望大家喜歡,覺(jué)得內(nèi)容不錯(cuò)的,歡迎「分享」「」或者點(diǎn)擊「在看」支持,謝謝各位。

          瀏覽 45
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  强开小嫩苞一区二区电影 | 伊人夜夜躁AV伊人久久 | 九九福利 | 国产高清无码视频在线 | 黄色1级片|