成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

聊聊Semaphore 信號量源碼分析

開發 項目管理
Semaphore 信號量, 信號量維護了一組許可。如果有必要每個采集模塊都會阻塞,直到有許可可用。然后獲取許可證。每次發布都會添加一個許可證,可能會釋放一個阻塞資源。

[[422207]]

本文轉載自微信公眾號「運維開發故事」,作者老鄭。轉載本文請聯系運維開發故事公眾號。

概述

Semaphore 信號量, 信號量維護了一組許可。如果有必要每個采集模塊都會阻塞,直到有許可可用。然后獲取許可證。每次發布都會添加一個許可證,可能會釋放一個阻塞資源。但是,沒有使用實際的許可對象;信號量可用數量的計數,并且進行操作。 信號量通常可以用于限制訪問某些(物理或者邏輯)資源的線程數。例如下面是一個使用信號量控制對線程池訪問。

  1. class Pool { 
  2.   private static final int MAX_AVAILABLE = 100; 
  3.   private final Semaphore available = new Semaphore(MAX_AVAILABLE, true); 
  4.  
  5.   public Object getItem() throws InterruptedException { 
  6.     available.acquire(); 
  7.     return getNextAvailableItem(); 
  8.   } 
  9.  
  10.   public void putItem(Object x) { 
  11.     if (markAsUnused(x)) 
  12.       available.release(); 
  13.   } 
  14.  
  15.   // Not a particularly efficient data structure; just for demo 
  16.  
  17.   protected Object[] items = ... whatever kinds of items being managed 
  18.   protected boolean[] used = new boolean[MAX_AVAILABLE]; 
  19.  
  20.   protected synchronized Object getNextAvailableItem() { 
  21.     for (int i = 0; i < MAX_AVAILABLE; ++i) { 
  22.       if (!used[i]) { 
  23.          used[i] = true
  24.          return items[i]; 
  25.       } 
  26.     } 
  27.     return null; // not reached 
  28.   } 
  29.  
  30.   protected synchronized boolean markAsUnused(Object item) { 
  31.     for (int i = 0; i < MAX_AVAILABLE; ++i) { 
  32.       if (item == items[i]) { 
  33.          if (used[i]) { 
  34.            used[i] = false
  35.            return true
  36.          } else 
  37.            return false
  38.       } 
  39.     } 
  40.     return false
  41.   } 

在獲取項目之前,每個線程必須從信號量獲取一個許可證,以確保項目可用。當線程處理完該項后,它將返回到池中,并向信號量返回一個許可證,允許另一個線程獲取該項。請注意,在調用acquire時不會保持同步鎖,因為這會阻止項目返回池。信號量封裝了限制對池的訪問所需的同步,與維護池本身一致性所需的任何同步分開。

初始化為1的信號量,其使用方式是最多只有一個可用的許可證,可以用作互斥鎖。這通常被稱為二進制信號量,因為它只有兩個狀態:一個許可證可用,或者零個許可證可用。以這種方式使用時,二進制信號量的屬性(與許多java.util.concurrent.locks.Lock實現不同)是“鎖”可以由所有者以外的線程釋放(因為信號量沒有所有權的概念)。這在某些特定的上下文中非常有用,例如死鎖恢復。

此類的構造函數可以選擇接受公平性參數。當設置為false時,此類不保證線程獲取許可的順序。特別是,允許bargging,也就是說,調用acquire的線程可以在一直在等待的線程之前分配一個許可證-從邏輯上講,新線程將自己置于等待線程隊列的頭部。當公平性設置為true時,信號量保證選擇調用任何acquire方法的線程,以按照其調用這些方法的處理順序(先進先出;先進先出)。請注意,FIFO排序必然適用于這些方法中的特定內部執行點。因此,一個線程可以在另一個線程之前調用acquire,但在另一個線程之后到達排序點,類似地,從方法返回時也是如此。還請注意,untimed tryAcquire方法不支持公平性設置,但將接受任何可用的許可。

通常,用于控制資源訪問的信號量應該初始化為公平,以確保沒有線程因訪問資源而耗盡。當將信號量用于其他類型的同步控制時,非公平排序的吞吐量優勢往往超過公平性考慮。

此類還提供了方便的方法,可以一次獲取和發布多個許可證。當使用這些方法時,如果沒有將公平設置為真,則要小心無限期延遲的風險增加。

內存一致性影響:在調用“release”方法(如release())之前的線程中的操作發生在另一個線程中成功的“acquire”方法(如acquire()之后的操作)之前。

原理分析

Semaphore 信號量,是控制并發的有效手段。它底層通過 AQS 實現。如下圖所示:

構造方法

Semaphore 構造方法有兩個 Semaphore(int permits) 和 Semaphore(int permits, boolean fair) 后者有兩個參數:第一個參數是許可數量初始化,第二個參數定義信號量是否公平鎖同步(默認為非公平)。

  1. public Semaphore(int permits) { 
  2.     sync = new NonfairSync(permits); 
  3.  
  4.  
  5. public Semaphore(int permits, boolean fair) { 
  6.     sync = fair ? new FairSync(permits) : new NonfairSync(permits); 

acquire 方法

acquire 方法可以為理解獲取許可,如果存在剩余許可那么就可以進入后續代碼塊,如果沒有獲取線程進入阻塞。在共享模式下獲取,如果中斷將中止。通過首先檢查中斷狀態,然后調用至少一次tryAcquireShared,并在成功時返回來實現。否則線程將排隊,可能會重復阻塞和取消阻塞,調用tryAcquireShared,直到成功或線程中斷。

release 方法

acquire 方法可以為理解釋放許可,其他等待許可的線程進入資源競爭階段。然后去查找等待隊列隊頭有效的等待節點進行喚醒。

整體流程

Semaphore 信號量原理.png

舉個例子

場景描述

對于控制流量,或者控制并發我們可以使用 Semaphore 信號量來完成。例子:有100 個人需要過橋,但是橋上最多同時能夠承受 5 個人的重量。如果我們需要有序的過橋那么就可以采用信號量的方式來控制。

初始化 5 個許可。

上橋之前先去獲取 許可,如果有剩余許可就上橋。

如果沒有 許可,就等待許可。

image.png

模擬代碼

首先定義橋對象,入下所示:

  1. public class Bridge { 
  2.  
  3.     private String name
  4.  
  5.     private String address; 
  6.  
  7.     private Integer max
  8.  
  9.     public String getName() { 
  10.         return name
  11.     } 
  12.  
  13.     public void setName(String name) { 
  14.         this.name = name
  15.     } 
  16.  
  17.     public String getAddress() { 
  18.         return address; 
  19.     } 
  20.  
  21.     public void setAddress(String address) { 
  22.         this.address = address; 
  23.     } 
  24.  
  25.     public Integer getMax() { 
  26.         return max
  27.     } 
  28.  
  29.     public void setMax(Integer max) { 
  30.         this.max = max
  31.     } 

然后定義遷徙者對象,就是過橋的人,然后他有個動作就是過橋。代碼如下所示。

  1. public class Migrator { 
  2.  
  3.     private String name
  4.  
  5.     public void gapBridge() { 
  6.         System.out.println("Migrator: " + this.name + ", time:" + System.currentTimeMillis()); 
  7.     } 
  8.  
  9.     public String getName() { 
  10.         return name
  11.     } 
  12.  
  13.     public void setName(String name) { 
  14.         this.name = name
  15.     } 

調用代碼如下:

  1. public class MainTest { 
  2.  
  3.     public static void main(String[] args) { 
  4.         Bridge bridge = new Bridge(); 
  5.         bridge.setAddress("云南"); 
  6.         bridge.setName("XX 橋"); 
  7.         bridge.setMax(5); 
  8.  
  9.         Semaphore semaphore = new Semaphore(bridge.getMax()); 
  10.         for (int i=0; i< 100; i++) { 
  11.             int idx = i; 
  12.             new Thread(()-> { 
  13.                 try { 
  14.                     Migrator migrator = new Migrator(); 
  15.                     migrator.setName("name-" + idx); 
  16.                     semaphore.acquire(); 
  17.                     TimeUnit.SECONDS.sleep(1); 
  18.                     migrator.gapBridge(); 
  19.                     System.out.println("name " + migrator.getName() + " 通過"); 
  20.                 } catch (InterruptedException e) { 
  21.                     e.printStackTrace(); 
  22.                 } finally { 
  23.                     semaphore.release(); 
  24.                 } 
  25.             }).start(); 
  26.         } 
  27.     } 

輸出日志如下:我們可以看到剛開始的時候有 5 個線程獲取到 "許可" 幾乎同時過橋,后面逐漸就是釋放一個許可,另外一個線程繼續執行。

  1. Migrator: name-7, time:1630495912011 
  2. name name-7 通過 
  3. Migrator: name-2, time:1630495912011 
  4. name name-2 通過 
  5. Migrator: name-4, time:1630495912011 
  6. Migrator: name-8, time:1630495912011 
  7. Migrator: name-3, time:1630495912011 
  8. name name-3 通過 
  9. name name-8 通過 
  10. name name-4 通過 
  11. Migrator: name-5, time:1630495913012 
  12. name name-5 通過 
  13. Migrator: name-0, time:1630495913012 
  14. name name-0 通過 
  15. Migrator: name-6, time:1630495913013 

參考文檔

 

https://www.cnblogs.com/leesf456/p/5414778.html

 

責任編輯:武曉燕 來源: 運維開發故事
相關推薦

2022-04-13 11:12:43

鴻蒙輕內核信號量模塊操作系統

2021-05-31 20:30:55

鴻蒙HarmonyOS應用

2020-11-05 09:59:24

Linux內核信號量

2021-04-13 09:20:15

鴻蒙HarmonyOS應用開發

2020-11-10 15:25:26

SemaphoreLinux翻譯

2021-04-30 00:00:50

Semaphore信號量面試官

2024-04-10 08:16:20

多線程編程Java并發編程

2010-04-21 16:50:31

Unix信號量

2025-04-16 08:50:00

信號量隔離線程池隔離并發控制

2010-04-21 16:25:13

Unix信號量

2010-04-21 16:42:48

Unix信號量

2010-04-21 15:37:38

Unix信號量

2020-09-25 07:34:40

Linux系統編程信號量

2023-06-02 08:14:58

信號量對象線程

2024-10-29 15:23:45

Python線程安全

2023-10-06 23:31:25

可視化Go

2019-11-19 09:00:38

JavaAND信號量

2009-12-08 12:14:43

2010-03-17 16:36:10

Java信號量模型

2010-07-15 15:32:10

Perl線程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 大象视频一区二区 | 亚洲精品久久嫩草网站秘色 | 亚洲精品视频免费看 | 国产精品99免费视频 | 亚洲麻豆 | 久久久久亚洲视频 | 在线视频一区二区 | 在线一区二区三区 | 黄色毛片一级 | 黄色成人在线网站 | 亚洲 欧美 另类 综合 偷拍 | 成人免费av | www网站在线观看 | 午夜精品久久久久久久久久久久久 | 日本一区二区三区免费观看 | 红色av社区 | 高清18麻豆| 免费亚洲一区二区 | 欧美成年人 | 伊人久久大香线 | 蜜桃视频一区二区三区 | 欧美日韩精品免费观看 | 中文字幕在线视频观看 | 欧美成人黄色小说 | 羞羞色在线观看 | 欧美成人一区二免费视频软件 | 精品国产精品一区二区夜夜嗨 | 91精品久久久久久久久 | 国产精品久久久久久久久久三级 | 久久久久成人精品免费播放动漫 | 黄色网络在线观看 | 精品欧美一区免费观看α√ | 国产午夜精品理论片a大结局 | 亚洲国产精品一区二区久久 | 涩涩视频在线观看 | 国产成人精品一区二三区在线观看 | 在线日韩欧美 | 国产成人精品免费视频大全最热 | 精品1区 | 天天草草草 | 国产乱码精品一区二区三区五月婷 |