<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Lock

      Lock

      • Lock和synchronized,這兩個是最常見的鎖,它們都可以達到線程安全的目的,但是在使用上和功能上又有較大的不同。
      • Lock并不是用來代替synchronized的,而是當使用synchronized不合適或不足以滿足要求的時候,來提供高級功能的。

      為什么synchronized不夠用

      1. 效率低:鎖的釋放情況少、試圖獲得鎖時不能設定超時、不能中斷一個正在試圖獲得鎖的線程
      2. 不夠靈活(讀寫鎖更靈活):加鎖和釋放的時機單一,每個鎖僅有單一的條件(某個對象),可能是不夠的
      3. 無法知道是否成功獲取到鎖

      Lock接口

      • 通常情況下,Lock只允許一個線程來訪問這個共享資源。不過有的時候,一些特殊的實現也可允許并發訪問,比如ReadWriteLock里面的ReadLock。

      ReentrantLock實現類

      既是互斥鎖,又是可重入鎖。

      獲取鎖方法

      lock()
      • lock()就是最普通的獲取鎖。如果鎖已被其他線程獲取,則進行等待
      • Lock不會像synchronized一樣在異常時自動釋放鎖,在finallly中釋放鎖,以保證發生異常時鎖一定被釋放

      coding

      /**

      * 描述: Lock不會像synchronized一樣,異常的時候自動釋放鎖,所以最佳實踐是,finally中釋放鎖,以便保證發生異常的時候鎖一定被釋放

      */

      public class MustUnlock {

      private static Lock lock = new ReentrantLock();

      public static void main(String[] args) {

      lock.lock();

      try{

      //獲取本鎖保護的資源

      System.out.println(Thread.currentThread().getName()+"開始執行任務");

      }finally {

      lock.unlock();

      }

      }

      }

      • lock()方法不能被中斷,這會帶來很大的隱患:一旦陷入死鎖,lock()就會陷入永久等待
      tryLock()
      • tryLock()用來嘗試獲取鎖,如果當前鎖沒有被其他線程占用則獲取成功,則返回true,否則返回false,代表獲取鎖失敗
      • 相比于lock,這樣的方法顯然功能更強大了,我們可以根據是否能獲取到鎖來決定后續程序的行為
      • 該方法會立即返回,即便在拿不到鎖時不會一直在那等
      tryLock(long time,TimeUnit unit)

      超時就放棄,避免死鎖

      coding

      **

      * 描述: 用tryLock來避免死鎖

      */

      public class TryLockDeadlock implements Runnable {

      int flag = 1;

      static Lock lock1 = new ReentrantLock();

      static Lock lock2 = new ReentrantLock();

      public static void main(String[] args) {

      TryLockDeadlock r1 = new TryLockDeadlock();

      TryLockDeadlock r2 = new TryLockDeadlock();

      r1.flag = 1;

      r2.flag = 0;

      new Thread(r1).start();

      new Thread(r2).start();

      }

      @Override

      public void run() {

      for (int i = 0; i < 10; i++) {

      if (flag == 1) {

      try {

      if (lock1.tryLock(800, TimeUnit.MILLISECONDS)) {

      try {

      System.out.println("線程1獲取到了鎖1");

      Thread.sleep(new Random().nextInt(1000));

      if (lock2.tryLock(800, TimeUnit.MILLISECONDS)) {

      try {

      System.out.println("線程1獲取到了鎖2");

      System.out.println("線程1成功獲取到了兩把鎖");

      break;

      } finally {

      lock2.unlock();

      }

      } else {

      System.out.println("線程1獲取鎖2失敗,已重試");

      }

      } finally {

      lock1.unlock();

      Thread.sleep(new Random().nextInt(1000));

      }

      } else {

      System.out.println("線程1獲取鎖1失敗,已重試");

      }

      } catch (InterruptedException e) {

      e.printStackTrace();

      }

      }

      if (flag == 0) {

      try {

      if (lock2.tryLock(3000, TimeUnit.MILLISECONDS)) {

      try {

      System.out.println("線程2獲取到了鎖2");

      Thread.sleep(new Random().nextInt(1000));

      if (lock1.tryLock(800, TimeUnit.MILLISECONDS)) {

      try {

      System.out.println("線程2獲取到了鎖1");

      System.out.println("線程2成功獲取到了兩把鎖");

      break;

      } finally {

      lock1.unlock();

      }

      } else {

      System.out.println("線程2獲取鎖1失敗,已重試");

      }

      } finally {

      lock2.unlock();

      Thread.sleep(new Random().nextInt(1000));

      }

      } else {

      System.out.println("線程2獲取鎖2失敗,已重試");

      }

      } catch (InterruptedException e) {

      e.printStackTrace();

      }

      }

      }

      }

      }

      ==============運行結果=============

      線程1獲取到了鎖1

      線程2獲取到了鎖2

      線程1獲取鎖2失敗,已重試

      線程2獲取到了鎖1

      線程2成功獲取到了兩把鎖

      線程1獲取到了鎖1

      線程1獲取到了鎖2

      線程1成功獲取到了兩把鎖

      lockInterruptibly()

      相當于tryLock(long time,TimeUnit unit)把超時時間設置為無限。在等待鎖的過程中,線程可以被中斷。

      coding

      public class LockInterruptibly implements Runnable {

      private Lock lock = new ReentrantLock();
      public static void main(String[] args) {
      LockInterruptibly lockInterruptibly = new LockInterruptibly();
      Thread thread0 = new Thread(lockInterruptibly);
      Thread thread1 = new Thread(lockInterruptibly);
      thread0.start();
      thread1.start();

      try {
      Thread.sleep(2000);
      } catch (InterruptedException e) {
      e.printStackTrace();
      }
      thread1.interrupt();
      }
      @Override
      public void run() {
      System.out.println(Thread.currentThread().getName() + "嘗試獲取鎖");
      try {
      lock.lockInterruptibly();
      try {
      System.out.println(Thread.currentThread().getName() + "獲取到了鎖");
      Thread.sleep(5000);
      } catch (InterruptedException e) {
      System.out.println(Thread.currentThread().getName() + "睡眠期間被中斷了");
      } finally {
      lock.unlock();
      System.out.println(Thread.currentThread().getName() + "釋放了鎖");
      }
      } catch (InterruptedException e) {
      System.out.println(Thread.currentThread().getName() + "獲得鎖期間被中斷了");
      }
      }
      }

      =============運行結果=============

      Thread-0嘗試獲取鎖

      Thread-1嘗試獲取鎖

      Thread-0獲取到了鎖

      Thread-1獲得鎖期間被中斷了

      Thread-0釋放了鎖

      isHeldByCurrentThread

      鎖是否被當前線程持有。

      一般調試開發使用

      getQueueLength

      返回當前正在等待這把鎖的隊列有多長。

      一般調試開發使用

      可見性

      Lock的加解鎖和synchronized有同樣的內存語義,也就是說,下一個線程加鎖后可以看到所有前一個線程解鎖前發生的所有操作

      synchronized可見性

      lock可見性

      鎖分類

      樂觀鎖和悲觀鎖

      樂觀鎖(非互斥同步鎖)

      • 認為自己在處理操作的時候不會有其他線程來干擾,所以并不會鎖住被操作對象
      • 在更新的時候,去對比在我修改的期間數據有沒有被其他人改變過:如果沒被改變過,就說明真的是只有我自己在操作,那我就正常去修改數據
      • 如果數據和我一開始拿到的不一樣了,說明其他人在這段時間內改過數據,那我就不能繼續剛才的更新數據過程了,我會選擇放棄、報錯、重試等策略
      • 樂觀鎖的實現一般都是利用CAS算法來實現的
      • 原子類、并發容器屬于樂觀鎖

      操作流程

      悲觀鎖(互斥同步鎖)

      • 如果我不鎖住這個資源,別人就會來爭搶,就會造成數據結果錯誤,所以每次悲觀鎖為了確保結果的正確性,會在每次獲取并修改數據時,把數據鎖住,讓別人無法訪問該數據,這樣就可以確保數據內容萬無一失
      • Java中悲觀鎖的實現就是synchronized和Lock相關類
      • 互斥同步鎖的劣勢
      • 阻塞和喚醒帶來的性能劣勢
      • 永久阻塞:如果持有鎖的線程被永久阻塞,比如遇到了無限循環、死鎖等活躍性問題,那么等待該線程釋放鎖的那幾個悲催的線程,將永遠也得不到執行
      • 優先級反轉
      • synchronized和lock接口屬于悲觀鎖

      悲觀鎖流程

      開銷對比

      • 悲觀鎖的原始開銷要高于樂觀鎖,但是特點是一勞永逸,l合||四界區持鎖時間就算越來越差,也不會對互斥鎖的開銷造成影響
      • 相反,雖然樂觀鎖一開始的開銷比悲觀鎖小,但是如果自旋時間很長或者不停重試,那么消耗的資源也會越來越多
      • 悲觀鎖:適合并發寫入多的情況,適用于臨界區持鎖時間比較長的情況,悲觀鎖可以避免大量的無用自旋等消耗,典型情況:
      1. 臨界區有IO操作

      2. 臨界區代碼復雜或者循環量大3臨界區競爭非常激烈

      • 樂觀鎖:適合并發寫入少,大部分是讀取的場景,不加鎖的能讓讀取性能大幅提高。

      可重入鎖和非可重入鎖

      可重入?

      再次申請鎖,無需釋放這把鎖,繼續使用這把鎖,也叫遞歸鎖。同一線程可多次獲取同一把鎖。

      優點:

      避免死鎖。

      提升封裝性。

      coding:

      public class GetHoldCount {
      private static ReentrantLock lock = new ReentrantLock();

      public static void main(String[] args) {
      System.out.println(lock.getHoldCount());
      lock.lock();
      System.out.println(lock.getHoldCount());
      lock.lock();
      System.out.println(lock.getHoldCount());
      lock.lock();
      System.out.println(lock.getHoldCount());
      lock.unlock();
      System.out.println(lock.getHoldCount());
      lock.unlock();
      System.out.println(lock.getHoldCount());
      lock.unlock();
      System.out.println(lock.getHoldCount());
      }
      }

      =======輸出結果========

      0

      1

      2

      3

      2

      1

      0

      coding

      public class RecursionDemo {

      private static ReentrantLock lock = new ReentrantLock();

      private static void accessResource() {
      lock.lock();
      try {
      System.out.println("已經對資源進行了處理");
      if (lock.getHoldCount()<5) {
      System.out.println(lock.getHoldCount());
      accessResource();
      System.out.println(lock.getHoldCount());
      }
      } finally {
      lock.unlock();
      }
      }
      public static void main(String[] args) {
      accessResource();
      }
      }

      ==========輸出結果============

      已經對資源進行了處理

      1

      已經對資源進行了處理

      2

      已經對資源進行了處理

      3

      已經對資源進行了處理

      4

      已經對資源進行了處理

      4

      3

      2

      1

      非可重入?

      ThreadPoolExecutor的Worker類

      公平鎖和非公平鎖

      公平指的是按照線程請求的順序,來分配鎖;非公平指的是,不完全按照請求的順序,在一定情況下,可以插隊。

      注意:非公平也同樣不提倡“插隊”行為,這里的非公平,指的是“在合適的時機”插隊,而不是盲目插隊。

      避免喚醒帶來的空檔期,提交高效.

      ReentrantLock創建公平鎖

      new ReentrantLock(true);

      公平情況

      不公平情況

      • 如果在線程1釋放鎖的時候,線程5恰好去執行lock()
      • 由于ReentrantLock發現此時并沒有線程持有lock這把鎖(線程2還沒來得及獲取到,因為獲取需要時間)
      • 線程5可以插隊,直接拿到這把鎖,這也是ReentrantLock默認的公平策略,也就是“不公平”

      coding

      /**
      * 描述: 演示公平和不公平兩種情況
      */
      public class FairLock {

      public static void main(String[] args) {
      PrintQueue printQueue = new PrintQueue();
      Thread thread[] = new Thread[10];
      for (int i = 0; i < 10; i++) {
      thread[i] = new Thread(new Job(printQueue));
      }
      for (int i = 0; i < 10; i++) {
      thread[i].start();
      try {
      Thread.sleep(100);
      } catch (InterruptedException e) {
      e.printStackTrace();
      }
      }
      }
      }

      class Job implements Runnable {

      PrintQueue printQueue;

      public Job(PrintQueue printQueue) {
      this.printQueue = printQueue;
      }

      @Override
      public void run() {
      System.out.println(Thread.currentThread().getName() + "開始打印");
      printQueue.printJob(new Object());
      System.out.println(Thread.currentThread().getName() + "打印完畢");
      }
      }

      class PrintQueue {

      private Lock queueLock = new ReentrantLock(true);//false不公平鎖

      public void printJob(Object document) {
      queueLock.lock();
      try {
      int duration = new Random().nextInt(10) + 1;
      System.out.println(Thread.currentThread().getName() + "正在打印,需要" + duration);
      Thread.sleep(duration * 1000);
      } catch (InterruptedException e) {
      e.printStackTrace();
      } finally {
      queueLock.unlock();
      }

      queueLock.lock();//創建的是公平鎖,當前線程想再次拿到鎖,發現隊列當中有線程排隊等待拿鎖,當前線程會進入隊列排隊等待

      //創建的是不公平鎖,當前線程會利用空檔期再次拿到鎖,向下繼續運行。
      try {
      int duration = new Random().nextInt(10) + 1;
      System.out.println(Thread.currentThread().getName() + "正在打印,需要" + duration+"秒");
      Thread.sleep(duration * 1000);
      } catch (InterruptedException e) {
      e.printStackTrace();
      } finally {
      queueLock.unlock();
      }
      }
      }

      ==============公平鎖輸出結果============

      Thread-0開始打印

      Thread-0正在打印,需要6

      Thread-1開始打印

      Thread-2開始打印

      Thread-1正在打印,需要2

      Thread-2正在打印,需要10

      Thread-0正在打印,需要6秒

      Thread-0打印完畢

      Thread-1正在打印,需要3秒

      Thread-1打印完畢

      Thread-2正在打印,需要3秒

      Thread-2打印完畢

      說明:公平鎖,線程會按順序排隊獲取鎖

      =============不公平鎖輸出結果=============

      Thread-0開始打印

      Thread-0正在打印,需要7

      Thread-1開始打印

      Thread-2開始打印

      Thread-0正在打印,需要4秒

      Thread-0打印完畢

      Thread-1正在打印,需要1

      Thread-1正在打印,需要8秒

      Thread-1打印完畢

      Thread-2正在打印,需要6

      Thread-2正在打印,需要4秒

      Thread-2打印完畢

      特例

      • 針對tryLock()方法,它是很猛的,它不遵守設定的公平的規則
      • 例如,當有線程執行tryLock()的時候,一旦有線程釋放了鎖,那么這個正在tryLock的線程就能獲取到鎖,即使在它之前已經有其他現在在等待隊列里了

      優缺點

      共享鎖和排它鎖

      • 排他鎖,又稱為獨占鎖、獨享鎖。

      synchronized屬于排它鎖

      • 共享鎖,又稱為讀鎖,獲得共享鎖之后,可以查看但無法修改和刪除數據,其他線程此時也可以獲取到共享鎖,也可以查看但無法修改和刪除數據
      • 共享鎖和排它鎖的典型是讀寫鎖ReentrantReadWriteLock,其中讀鎖是共享鎖,寫鎖是獨享鎖

      作用

      • 在沒有讀寫鎖之前,我們假設使用ReentrantLock,那么雖然我們保證了線程安全,但是也浪費了一定的資源:多個讀操作同時進行,并沒有線程安全問題
      • 在讀的地方使用讀鎖,在寫的地方使用寫鎖,靈活控制,如果沒有寫鎖的情況下,讀是無阻塞的,提高了程序的執行效率

      規則

      a)多個線程只申請讀鎖,都可以申請到

      b)如果有一個線程已經占用了讀鎖,則此時其他線程如果要申請寫鎖,則申請寫鎖的線程會一直等待釋放讀鎖。

      c)如果有一個線程已經占用了寫鎖,則此時其他線程如果申請寫鎖或者讀鎖,則申請的線程會一直等待釋放寫鎖。

      d)一句話總結:要么是一個或多個線程同時有讀鎖,要么是一個線程有寫鎖,但是兩者不會同時出現(要么多讀,要多一寫)

      換一種思路更容易理解:讀寫鎖只是一把鎖,可以通過兩種方式鎖定:讀鎖定和寫鎖定。讀寫鎖可以同時被一個或多個線程讀鎖定,也可以被單一線程寫鎖定。但是永遠不能同時對這把鎖進行讀鎖定和寫鎖定。這里是把“獲取寫鎖”理解為“把讀寫鎖進行寫鎖定”相當于是換了一種思路,不過原則是不變的,就是要么是一個或多個線程同時有讀鎖(同時讀鎖定),要么是一個線程有寫鎖(進行寫鎖定),但是兩者不會同時出現

      ReentrantReadWriteLock用法

      public class CinemaReadWrite {

      private static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
      private static ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
      private static ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();

      private static void read() {
      readLock.lock();
      try {
      System.out.println(Thread.currentThread().getName() + "得到了讀鎖,正在讀取");
      Thread.sleep(1000);
      } catch (InterruptedException e) {
      e.printStackTrace();
      } finally {
      System.out.println(Thread.currentThread().getName() + "釋放讀鎖");
      readLock.unlock();
      }
      }

      private static void write() {
      writeLock.lock();
      try {
      System.out.println(Thread.currentThread().getName() + "得到了寫鎖,正在寫入");
      Thread.sleep(1000);
      } catch (InterruptedException e) {
      e.printStackTrace();
      } finally {
      System.out.println(Thread.currentThread().getName() + "釋放寫鎖");
      writeLock.unlock();
      }
      }

      public static void main(String[] args) {
      new Thread(()->read(),"Thread1").start();
      new Thread(()->read(),"Thread2").start();
      new Thread(()->write(),"Thread3").start();
      new Thread(()->write(),"Thread4").start();
      }
      }

      ========輸出=======

      Thread1得到了讀鎖,正在讀取

      Thread2得到了讀鎖,正在讀取

      Thread2釋放讀鎖

      Thread1釋放讀鎖

      Thread3得到了寫鎖,正在寫入

      Thread3釋放寫鎖

      Thread4得到了寫鎖,正在寫入

      Thread4釋放寫鎖

      交互規則

      不允許讀鎖插隊(公平)

      允許寫鎖降為讀鎖,不允許讀鎖升為寫鎖

      非公平和公平的ReentrantReadWriteLock的策略

      公平鎖:不允許插隊

      非公平鎖:

      寫鎖可以隨時插隊

      讀鎖僅在等待隊列頭結點不是想獲取寫鎖的線程時可以插隊

      非公平:假設線程2和線程4正在同時讀取,線程3想要寫入拿不到鎖,于是進入等待隊列,線程5不在隊列里,現在過來想要讀取

      此時有2種策略

      public class NonfairBargeDemo {

      private static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(
      true); //false非公平鎖

      private static ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
      private static ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();

      private static void read() {
      System.out.println(Thread.currentThread().getName() + "開始嘗試獲取讀鎖");
      readLock.lock();
      try {
      System.out.println(Thread.currentThread().getName() + "得到讀鎖,正在讀取");
      try {
      Thread.sleep(20);
      } catch (InterruptedException e) {
      e.printStackTrace();
      }
      } finally {
      System.out.println(Thread.currentThread().getName() + "釋放讀鎖");
      readLock.unlock();
      }
      }

      private static void write() {
      System.out.println(Thread.currentThread().getName() + "開始嘗試獲取寫鎖");
      writeLock.lock();
      try {
      System.out.println(Thread.currentThread().getName() + "得到寫鎖,正在寫入");
      try {
      Thread.sleep(40);
      } catch (InterruptedException e) {
      e.printStackTrace();
      }
      } finally {
      System.out.println(Thread.currentThread().getName() + "釋放寫鎖");
      writeLock.unlock();
      }
      }

      public static void main(String[] args) {
      new Thread(()->write(),"Thread1").start();
      new Thread(()->read(),"Thread2").start();
      new Thread(()->read(),"Thread3").start();
      new Thread(()->write(),"Thread4").start();
      new Thread(()->read(),"Thread5").start();
      new Thread(new Runnable() {
      @Override
      public void run() {
      Thread thread[] = new Thread[1000];
      for (int i = 0; i < 1000; i++) {
      thread[i] = new Thread(() -> read(), "子線程創建的Thread" + i);
      }
      for (int i = 0; i < 1000; i++) {
      thread[i].start();
      }
      }
      }).start();
      }
      }

      鎖升降級

      寫鎖可降級讀鎖

      讀鎖不可升級寫鎖,否則死鎖。

      public class Upgrading {

      private static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(
      false);
      private static ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
      private static ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();

      private static void readUpgrading() {
      readLock.lock();
      try {
      System.out.println(Thread.currentThread().getName() + "得到了讀鎖,正在讀取");
      Thread.sleep(1000);
      System.out.println("升級會帶來阻塞");
      writeLock.lock();
      System.out.println(Thread.currentThread().getName() + "獲取到了寫鎖,升級成功");
      } catch (InterruptedException e) {
      e.printStackTrace();
      } finally {
      System.out.println(Thread.currentThread().getName() + "釋放讀鎖");
      readLock.unlock();
      }
      }

      private static void writeDowngrading() {
      writeLock.lock();
      try {
      System.out.println(Thread.currentThread().getName() + "得到了寫鎖,正在寫入");
      Thread.sleep(1000);
      readLock.lock();
      System.out.println("在不釋放寫鎖的情況下,直接獲取讀鎖,成功降級");
      } catch (InterruptedException e) {
      e.printStackTrace();
      } finally {
      readLock.unlock();
      System.out.println(Thread.currentThread().getName() + "釋放寫鎖");
      writeLock.unlock();
      }
      }

      public static void main(String[] args) throws InterruptedException {
      // System.out.println("先演示降級是可以的");
      // Thread thread1 = new Thread(() -> writeDowngrading(), "Thread1");
      // thread1.start();
      // thread1.join();
      // System.out.println("------------------");
      // System.out.println("演示升級是不行的");
      Thread thread2 = new Thread(() -> readUpgrading(), "Thread2");
      thread2.start();
      }
      }

      自旋鎖和阻塞鎖

      • 阻塞或喚醒一個Java線程需要操作系統切換CPU狀態來完成,這種狀態轉換需要耗費處理器時間
      • 如果同步代碼塊中的內容過于簡單,狀態轉換消耗的時間有可能比用戶代碼執行的時間還要長
      • 在許多場景中,同步資源的鎖定時間很短,為了這一小段時間去切換線程,線程掛起和恢復現場的花費可能會讓系統得不償失
      • 如果物理機器有多個處理器,能夠讓兩個或以上的線程同時并行執行,我們就可以讓后面那個請求鎖的線程不放棄CPU的執行時間,看看持有鎖的線程是否很快就會釋放鎖
      • 而為了讓當前線程“稍等一下”,我們需讓當前線程進行自旋,如果在自旋完成后前面鎖定同步資源的線程已經釋放了鎖,那么當前線程就可以不必阻塞而是直接獲取同步資源,從而避免切換線程的開銷。這就是自旋鎖。
      • 阻塞鎖和自旋鎖相反,阻塞鎖如果遇到沒拿到鎖的情況,會直接把線程阻塞,直到被喚醒
      • 在java1.5版本及以上的并發框架java.util.concurrent的atmoic包下的類基本都是自旋鎖的實現
      • AtomicInteger的實現:自旋鎖的實現原理是CAS,AtomicInteger中調用unsafe進行自增操作的源碼中的do-while循環就是一個自旋操作,如果修改過程中遇到其他線程競爭導致沒修改成功,就在while里死循環,直至修改成功

      /**
      * 描述: 自旋鎖
      */
      public class SpinLock {

      private AtomicReference<Thread> sign = new AtomicReference<>();

      public void lock() {
      Thread current = Thread.currentThread();
      while (!sign.compareAndSet(null, current)) {
      System.out.println(current.getName() + "自旋獲取失敗,再次嘗試");
      }
      }

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

      public static void main(String[] args) {
      SpinLock spinLock = new SpinLock();
      Runnable runnable = new Runnable() {
      @Override
      public void run() {
      System.out.println(Thread.currentThread().getName() + "開始嘗試獲取自旋鎖");
      spinLock.lock();
      System.out.println(Thread.currentThread().getName() + "獲取到了自旋鎖");
      try {
      Thread.sleep(300);
      } catch (InterruptedException e) {
      e.printStackTrace();
      } finally {
      spinLock.unlock();
      System.out.println(Thread.currentThread().getName() + "釋放了自旋鎖");
      }
      }
      };
      Thread thread1 = new Thread(runnable);
      Thread thread2 = new Thread(runnable);
      thread1.start();
      thread2.start();
      }
      }

      可中斷鎖

      • 在Java中,synchronized就不是可中斷鎖,而Lock是可中斷鎖,因為tryLock(time)和lockInterruptibly都能響應中斷。
      • 如果某一線程A正在執行鎖中的代碼,另一線程B正在等待獲取該鎖可能由于等待時間過長,線程B不想等待了,想先處理其他事情,我們可以中斷它,這種就是可中斷鎖

      鎖優化

      1. 縮小同步代碼塊
      2. 盡量不要鎖住方法
      3. 減少請求鎖的次數
      4. 避免人為制造“熱點”
      5. 鎖中盡量不要再包含鎖
      6. 選擇合適的鎖類型或合適的工具類
      posted @ 2024-01-31 19:04  wangzhilei  閱讀(79)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 欧美XXXX黑人又粗又长| 亚洲国产美女精品久久久| 妺妺窝人体色www婷婷| 亚洲欧美日韩综合一区在线| 久久一日本道色综合久久| 黑人巨大精品oideo| 男人的天堂av社区在线| AV秘 无码一区二| 久久se精品一区二区三区| 中文字字幕在线中文乱码| 亚洲综合精品一区二区三区| 国产国拍亚洲精品永久软件| 中文字幕有码高清日韩| 精品亚洲国产成人| 国产愉拍91九色国产愉拍| 成人国产精品免费网站| 国产午夜福利在线机视频| 亚洲国产成人午夜在线一区| 99久久久国产精品免费无卡顿| 亚洲午夜福利网在线观看| 无码专区视频精品老司机| 国产免费午夜福利蜜芽无码| 精品一区二区免费不卡| 少妇放荡的呻吟干柴烈火动漫| 亚洲国产日韩欧美一区二区三区| 国产激情无码一区二区APP| 国产午夜福利视频合集| 蜜臀av一区二区三区精品| 精品无码人妻| 人人澡人人妻人人爽人人蜜桃| 久久成人 久久鬼色| 亚洲欧美成人综合久久久| 农村熟女大胆露脸自拍| 99精品热在线在线观看视| 日韩女同一区二区三区久久| 日本无码欧美一区精品久久| 一区二区中文字幕久久| 黄网站色视频免费观看| 午夜男女爽爽影院在线| 狠狠色噜噜狠狠亚洲AV| 漂亮人妻中文字幕丝袜|