国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Java并發編程(JUC)模擬AND型信號量

開發 后端
AND型信號量可能大家都聽說過并可能都有一定的理解,但是你有使用過么?今天就使用Java來模擬實現!

AND型信號量可能大家都聽說過并可能都有一定的理解,但是你有使用過么?今天就使用Java來模擬實現!

[[282783]]

本文是對上篇文章(進程同步機制)的一次實踐,通過JUC提供的一些機制來模擬一些OS中的AND型信號量,因為記錄型型信號量可以等價于JUC中提供的Semaphore(信號量),但是對于AND型信號量因為一些原因(主要是過時了),JUC沒有提供,今天就手動的來寫一個AND型信號量對應的Swait操作和Ssignal操作(這里不明白的可以看前面的理論篇)。通過本篇博文讓你對進程同步機制有個更好的理解。

1.一個錯誤示例

在這里,首先解釋一下,為了滿足線程申請信號量不成功后將進程阻塞,并插入到對應的隊列中,所以使用了ReentrantLock+Condition來實現Swait方法。廢話不多說,直接上代碼:

  1. //數據定義 
  2.  
  3. static Lock lock = new ReentrantLock(); 
  4.  
  5. static Condition condition1 = lock.newCondition(); 
  6.  
  7. static Condition condition2 = lock.newCondition(); 
  8.  
  9. public static void Swait(String id, Semaphore s1, Semaphore s2) throws InterruptedException { 
  10.  
  11. lock.tryLock(1, TimeUnit.SECONDS); 
  12.  
  13. log.info("當前的兩個信號量的狀態:【{},{}】", s1.availablePermits(), s2.availablePermits()); 
  14.  
  15. //availablePermits可獲取到信號量中還剩余的值 
  16.  
  17. if(s1.availablePermits() < 1 || s2.availablePermits() < 1){ 
  18.  
  19. if (s1.availablePermits() < 1) { 
  20.  
  21. log.info("線程【{}】被掛起到信號量【{}】中", id, s1); 
  22.  
  23. //阻塞,并插入到condition1的阻塞隊列中 
  24.  
  25. condition1.await(); 
  26.  
  27. else { 
  28.  
  29. log.info("線程【{}】被掛起到信號量【{}】中", id, s2); 
  30.  
  31. //阻塞,并插入到condition2的阻塞隊列中 
  32.  
  33. condition2.await(); 
  34.  
  35.  
  36. log.info("被掛起的線程【{}】被喚醒執行。", id); 
  37.  
  38. else { 
  39.  
  40. log.info("為線程【{}】分配資源!", id); 
  41.  
  42. s1.acquire(); 
  43.  
  44. s2.acquire(); 
  45.  
  46.  
  47. lock.unlock(); 
  48.  
  49.  
  50. public static void Ssignal(Semaphore s1, Semaphore s2) throws InterruptedException { 
  51.  
  52. log.info("線程【{}】執行了釋放資源", id); 
  53.  
  54. lock.tryLock(1, TimeUnit.SECONDS); 
  55.  
  56. s1.release(); 
  57.  
  58. s2.release(); 
  59.  
  60. //喚醒等待隊列中的線程 
  61.  
  62. condition.signal(); 
  63.  
  64. lock.unlock(); 
  65.  

​ 大家仔細看上面的代碼,這個也是我剛開始寫的代碼,第一眼看似乎是沒什么問題,但是里面隱藏著一個坑,在Swait方法中,調用condition1.await(),此時線程被阻塞在這一行中,但是當被別的線程(調用Ssignal)喚醒時,在被阻塞的下一行開始繼續執行,但是在后續的代碼里,是沒有去申請信號量的,而是直接就Swait成功了,這樣在執行Ssignal時就會導致信號量憑空的增加了,也就無法正確的表征系統中的資源數量了。

2.一個簡單的示例

​ 下面我們就對代碼進行優化,大家可以回顧一下AND型信號量,當其因為資源不足時,需要將線程插入到第一個無法滿足條件(即Si<1)的信號量對應的等待隊列中,并且將程序計數器放置到Swait操作的開始處,所以我們對Swait代碼進行修改如下:

  1. public static void Swait(String id, Semaphore s1, Semaphore s2) throws InterruptedException { 
  2.  
  3. lock.tryLock(1, TimeUnit.SECONDS); 
  4.  
  5. log.info("當前的兩個信號量的狀態:【{},{}】", s1.availablePermits(), s2.availablePermits()); 
  6.  
  7. //如果申請不到,就掛起線程,并將線程插入到condition的隊列中 
  8.  
  9. while (s1.availablePermits() < 1 || s2.availablePermits() < 1) { 
  10.  
  11. if (s1.availablePermits() < 1) { 
  12.  
  13. log.info("線程【{}】被掛起到信號量【{}】中", id, s1); 
  14.  
  15. condition1.await(); 
  16.  
  17. else { 
  18.  
  19. log.info("線程【{}】被掛起到信號量【{}】中", id, s2); 
  20.  
  21. condition2.await(); 
  22.  
  23.  
  24. log.info("被掛起的線程【{}】被喚醒執行。", id); 
  25.  
  26.  
  27. log.info("為線程【{}】分配資源!", id); 
  28.  
  29. s1.acquire(); 
  30.  
  31. s2.acquire(); 
  32.  
  33. lock.unlock(); 
  34.  

​ 在上面的代碼中,我們將請求的資源放到一個循環條件中,以滿足將程序計數器放置到Swait操作的開始處,在每次被喚醒后都要重新判斷資源是否足夠,如果足夠才跳出循環,否則就再次自我阻塞。

3.一個可以同時申請N個的Swait操作

​ 如果你知道了信號量的種類數(系統中的資源類型),其實上面的代碼已經可以滿足一定的需要了,只需要我們將所有的信號量寫入到參數列表中即可。但是對于致力于代碼的復用,這里就有些差強人意了,因此我們再次對代碼進行改進,代碼如下所示:

  1. public static void Swait(String id, Semaphore... list) throws InterruptedException { 
  2.  
  3. lock.lock(); 
  4.  
  5. //如果資源不足,就掛起線程,并將線程插入到condition的隊列中 
  6.  
  7. while (true) { 
  8.  
  9. int count=0; 
  10.  
  11. //循環判斷參數列表中信號量的可用值 
  12.  
  13. for (Semaphore semaphore:list){ 
  14.  
  15. if(semaphore.availablePermits()>0){ 
  16.  
  17. count++; 
  18.  
  19.  
  20.  
  21. //如果資源都滿足,則跳出循環,進行資源分配 
  22.  
  23. if(count == list.length){ 
  24.  
  25. break; 
  26.  
  27.  
  28. log.info("線程【{}】被掛起-----", id); 
  29.  
  30. //將當前線程阻塞 
  31.  
  32. condition1.await(); 
  33.  
  34. log.info("被掛起的線程【{}】被喚醒執行。", id); 
  35.  
  36.  
  37. log.info("為線程【{}】分配資源!", id); 
  38.  
  39. //分配資源 
  40.  
  41. for (Semaphore semaphore:list){ 
  42.  
  43. semaphore.acquire(); 
  44.  
  45.  
  46. lock.unlock(); 
  47.  
  48.  
  49. public static void Ssignal(String id, Semaphore... list) throws InterruptedException { 
  50.  
  51. log.info("線程【{}】執行了釋放資源", id); 
  52.  
  53. lock.tryLock(1, TimeUnit.SECONDS); 
  54.  
  55. //循環釋放信號量 
  56.  
  57. for (Semaphore semaphore:list){ 
  58.  
  59. semaphore.release(); 
  60.  
  61.  
  62. //喚醒等待隊列中的線程 
  63.  
  64. condition.signal(); 
  65.  
  66. lock.unlock(); 
  67.  

​ 為此,我們將方法中的信號量列表改為可變的參數列表,這樣在傳參的時候就可以方便的進行了,但是也會存才一些問題,比如無法約束“借出”與“歸還”的信號量的數量是否一致。并且因為信號量的數量不定,所以無法為每個信號量新建一個條件變量(Condition),因此在上面的代碼中所有的信號量公用一個條件變量,所有阻塞的線程都插入在其阻塞隊列中。

4.一個完整的例子

​ 這里我們使用一個經典的進程同步問題來演示我們使用Java模擬的AND型信號量,在這里,我們采用生產者–消費者問題來演示,完整的代碼如下:

  1. //用來保證互斥的訪問臨界區(緩存區) 
  2.  
  3. static final Semaphore mutex = new Semaphore(1); 
  4.  
  5. //緩沖區,最大容量為50 
  6.  
  7. static List<Integer> buffer = new ArrayList<>(); 
  8.  
  9. //緩沖區中還可放入的消息數量 
  10.  
  11. static final Semaphore empty = new Semaphore(50); 
  12.  
  13. //緩沖區中的消息數量 
  14.  
  15. static final Semaphore full = new Semaphore(0); 
  16.  
  17. //可重入鎖和條件變量 
  18.  
  19. static Lock lock = new ReentrantLock(); 
  20.  
  21. static Condition condition = lock.newCondition(); 
  22.  
  23. //用與輔助的簡單的生成消息 
  24.  
  25. static Integer count = 0; 
  26.  
  27. //生產者 
  28.  
  29. static class Producer extends Thread { 
  30.  
  31. Producer(String name) { 
  32.  
  33. super.setName(name); 
  34.  
  35.  
  36. @Override 
  37.  
  38. public void run() { 
  39.  
  40. do { 
  41.  
  42. try { 
  43.  
  44. Swait(this.getName(), mutex, empty); 
  45.  
  46. log.info("生產了一條消息:【{}】"count); 
  47.  
  48. buffer.add(count++); 
  49.  
  50. Thread.sleep(1000); 
  51.  
  52. Ssignal(this.getName(), mutex, full); 
  53.  
  54. } catch (InterruptedException e) { 
  55.  
  56. log.error("生產消息時產生異常!"); 
  57.  
  58.  
  59. } while (true); 
  60.  
  61.  
  62.  
  63. //消費者 
  64.  
  65. static class Consumer extends Thread { 
  66.  
  67. Consumer(String name) { 
  68.  
  69. super.setName(name); 
  70.  
  71.  
  72. @Override 
  73.  
  74. public void run() { 
  75.  
  76. do { 
  77.  
  78. try { 
  79.  
  80. Swait(this.getName(), mutex, full); 
  81.  
  82. log.info("消費了一條消息:【{}】", buffer.remove(0)); 
  83.  
  84. Thread.sleep(1000); 
  85.  
  86. Ssignal(this.getName(), mutex, empty); 
  87.  
  88. } catch (InterruptedException e) { 
  89.  
  90. log.error("消費消息時產生異常!"); 
  91.  
  92.  
  93. } while (true); 
  94.  
  95.  
  96.  
  97. public static void Swait(String id, Semaphore... list) throws InterruptedException { 
  98.  
  99. lock.lock(); 
  100.  
  101. //如果資源不足,就掛起線程,并將線程插入到condition的隊列中 
  102.  
  103. while (true) { 
  104.  
  105. int count=0; 
  106.  
  107. for (Semaphore semaphore:list){ 
  108.  
  109. if(semaphore.availablePermits()>0){ 
  110.  
  111. count++; 
  112.  
  113.  
  114.  
  115. if(count == list.length){ 
  116.  
  117. break; 
  118.  
  119.  
  120. log.info("線程【{}】被掛起", id); 
  121.  
  122. condition.await(); 
  123.  
  124. log.info("被掛起的線程【{}】被喚醒執行。", id); 
  125.  
  126.  
  127. log.info("為線程【{}】分配資源!", id); 
  128.  
  129. for (Semaphore semaphore:list){ 
  130.  
  131. semaphore.acquire(); 
  132.  
  133.  
  134. lock.unlock(); 
  135.  
  136.  
  137. public static void Ssignal(String id, Semaphore... list) throws InterruptedException { 
  138.  
  139. log.info("線程【{}】執行了釋放資源", id); 
  140.  
  141. lock.tryLock(1, TimeUnit.SECONDS); 
  142.  
  143. for (Semaphore semaphore:list){ 
  144.  
  145. semaphore.release(); 
  146.  
  147.  
  148. //喚醒等待隊列中的一個線程 
  149.  
  150. condition.signal(); 
  151.  
  152. lock.unlock(); 
  153.  
  154.  
  155. public static void main(String[] args) { 
  156.  
  157. Producer p1 = new Producer("p1"); 
  158.  
  159. Consumer c1 = new Consumer("c1"); 
  160.  
  161. p1.start(); 
  162.  
  163. c1.start(); 
  164.  

​ 上面代碼都是可以直接執行的,如果不需要使用參數列表,可以將上面的Swait方法進行替換即可(記得創建對應的條件變量)。

​ 下圖是部分的執行結果: 

程序員:Java并發編程(JUC)模擬AND型信號量

又到了分隔線以下,本文到此就結束了,本文內容全部都是由博主自己進行整理并結合自身的理解并且進行的代碼編寫,如果有什么錯誤,還請批評指正。

​ 本文的所有java代碼都已通過測試,對其中有什么疑惑的,可以評論區留言,歡迎你的留言與討論;另外原創不易,如果本文對你有所幫助,還請留下個贊,以表支持。

​ 希望本文可以幫助你理解加深理解進程同步,也可以幫助你理解Java并發編程.

 

責任編輯:武曉燕 來源: Csdn博客
相關推薦

2016-11-23 16:08:24

Python處理器分布式系統

2020-09-25 07:34:40

Linux系統編程信號量

2024-04-10 08:16:20

多線程編程Java并發編程

2009-12-08 12:14:43

2021-04-13 09:20:15

鴻蒙HarmonyOS應用開發

2010-04-21 16:50:31

Unix信號量

2020-11-05 09:59:24

Linux內核信號量

2010-04-21 16:25:13

Unix信號量

2021-09-07 07:53:42

Semaphore 信號量源碼

2010-04-21 16:42:48

Unix信號量

2010-04-21 15:37:38

Unix信號量

2010-03-17 16:36:10

Java信號量模型

2024-07-25 11:53:53

2010-03-16 17:52:27

Java多線程信號量

2024-10-29 15:23:45

Python線程安全

2010-07-15 15:32:10

Perl線程

2010-04-21 17:10:25

Unix信號量

2021-02-03 20:10:29

Linux信號量shell

2017-05-11 14:05:25

Consul分布式信號量

2020-11-10 15:25:26

SemaphoreLinux翻譯
點贊
收藏

51CTO技術棧公眾號

www国产免费| 福利在线视频网站| 91精品国产91久久久久久密臀| 亚洲国产精品一区二区三区| 日本韩国一区| 综合在线观看色| www黄色日本| 国内国产精品久久| 午夜精品短视频| 99在线|亚洲一区二区| 国产精品美女网站| 欧美亚洲tv| 午夜精品一区二区三区在线视频| 日韩欧美一区二区三区在线观看| 日韩欧美国产一区二区三区| 超碰国产在线观看| 一本久道久久综合中文字幕| 永久www成人看片| 亚洲色大成网站www久久九九| 99久久久无码国产精品6| 国产99精品国产| 91制片厂免费观看| 国产精品99久久久久久有的能看 | 国产精品久久久久久久久妇女| 国a精品视频大全| 久久在线观看| 欧美巨猛xxxx猛交黑人97人| 中文成人在线| 欧美极品第一页| 亚洲午夜精品| 97久久久免费福利网址| 国产精品久久久久av蜜臀| 久久综合电影一区| 欧美大片91| 91av在线精品| 不卡av一区二区| 91理论片午午论夜理片久久| 欧美特黄一区| 欧美日韩最好看的视频| 免费人成网站在线观看欧美高清| 亚洲福利av| 国产69精品一区二区亚洲孕妇| 日本a在线天堂| 92精品国产成人观看免费| 成人在线观看你懂的| 久久久久高清精品| 亚洲国产日韩欧美在线观看| 一区二区三区精品在线观看| 视频二区在线| 欧美精品丝袜中出| 不卡视频观看| www.日韩.com| 欧美日韩一本| 亚洲伊人第一页| 天堂精品中文字幕在线| 中文字幕第一页亚洲| 91色乱码一区二区三区| 久久.com| 欧美性色视频在线| 91超碰在线| 久久久久久97| 欧美日韩爆操| 糖心vlog在线免费观看| 欧美国产成人在线| 成年人在线观看| 亚洲视频欧美视频| 日韩av三区| 国产伦精品一区二区三区视频黑人| 蜜桃视频第一区免费观看| 欧美黄网站在线观看| 黄色成人av网| 久久久一本精品| 成人精品视频在线| 国产成人亚洲综合a∨婷婷图片| 激情四房婷婷| 亚洲第一色中文字幕| 欧美sss在线视频| 久久www免费人成精品| 成人久久视频在线观看| 国产香蕉视频在线观看| 亚洲国产高清福利视频| 五月天亚洲一区| 亚洲国产精品一区二区第一页| 国产日产欧美一区| 国产激情小视频在线| 久久久久久久久久久成人| 亚洲综合好骚| 嫩草嫩草嫩草嫩草| 国产香蕉一区二区三区在线视频| 99久久精品国产亚洲精品| www.国产在线视频| 欧美日韩国产乱码电影| 日韩高清影视在线观看| 国产精品美女在线播放| 亚洲一区二区三区激情| 欧美黄色三级| 国产精选一区二区| 亚洲欧美一区二区三区国产精品| 国产精品亚洲二区| 日韩精品一区二区三区不卡| 国产精品理论片在线观看| 亚洲国产欧洲综合997久久 | 国产精品国产一区| 国产婷婷视频在线| 日日碰狠狠丁香久燥| 亚洲老司机av| 国产精品视频免费看| 久久不见久久见免费视频7| 在线观看三级视频| gogo在线高清视频| 在线小视频网址| 国产精品免费一区豆花| 国产精品福利av| 久久精品国产福利| 91麻豆天美传媒在线| 色综合夜色一区| 日韩人体视频| 高清hd写真福利在线播放| 91精品成人久久| 欧美视频在线不卡| 樱花草国产18久久久久| 国产精品短视频| 秋霞影院一区| 丝袜亚洲欧美日韩综合| 91久久久久| 色网址在线观看| 欧美激情区在线播放| 我要看一级黄色大片| 先锋影音一区二区三区| 国产一区二区三区三区在线观看| 欧美激情a在线| 成人毛片老司机大片| а天堂中文在线官网| 成人91视频| 日韩欧美在线视频观看| 香蕉av一区二区| julia京香一区二区三区| 4p变态网欧美系列| 国产精品高清亚洲| 亚洲精品一二三**| 精品第一国产综合精品aⅴ| 国产网站一区二区| 日本免费精品| 国内精品伊人久久| www午夜视频| 免费的一级黄色片| 电影午夜精品一区二区三区| 国产高清久久久| 蜜桃视频动漫在线播放| 日本一区二区三区免费看| 欧美性受xxxx黑人xyx性爽| 综合激情婷婷| 国产精品二线| 欧美性xxxx69| 精品日产卡一卡二卡麻豆| 老司机久久99久久精品播放免费| 精品国产欧美一区二区五十路| 国产成人免费av在线| 亚洲成人1区| 久草在线资源网站| 成人在线免费观看视视频| 91成人在线精品| 日本人妖一区二区| 日本免费在线一区| 成人au免费视频影院| 成人中文字幕+乱码+中文字幕| 欧美日韩成人在线一区| 国产一区视频导航| 欧洲一区在线| 伊人av免费在线观看| 蜜桃传媒视频麻豆一区| 亚洲性xxxx| 亚洲欧美日韩人成在线播放| 欧美激情精品久久久六区热门| 日本视频在线播放| a级片一区二区| 欧洲成人在线观看| 正在播放一区二区| 久久久久国产成人精品亚洲午夜 | 亚洲va久久久噜噜噜| 91精品欧美一区二区三区综合在| 国内精品伊人久久久久av影院| 51精品国产| 色的视频在线免费看| 久久艹国产精品| 国产精品96久久久久久又黄又硬| 欧美三级电影精品| 成人av影院在线| 日韩电影免费网站| 国模精品视频| 男女小视频在线观看| 天天爱天天做天天操| 国产v综合ⅴ日韩v欧美大片| 欧美精品一区二区高清在线观看| 国产精品丝袜91| 久久久久综合| 欧美人妖在线观看| jizz内谢中国亚洲jizz| 深夜福利在线观看直播| 久久久一本二本三本|