欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

JUC怎么模擬AND型信號量

這篇文章主要介紹“JUC怎么模擬AND型信號量”,在日常操作中,相信很多人在JUC怎么模擬AND型信號量問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”JUC怎么模擬AND型信號量”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

成都創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),廣南企業(yè)網(wǎng)站建設(shè),廣南品牌網(wǎng)站建設(shè),網(wǎng)站定制,廣南網(wǎng)站建設(shè)報價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,廣南網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。

1.一個錯誤示例

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

//數(shù)據(jù)定義  static Lock lock = new ReentrantLock();  static Condition condition1 = lock.newCondition();  static Condition condition2 = lock.newCondition();  public static void Swait(String id, Semaphore s1, Semaphore s2) throws InterruptedException {  lock.tryLock(1, TimeUnit.SECONDS);  log.info("當(dāng)前的兩個信號量的狀態(tài):【{},{}】", s1.availablePermits(), s2.availablePermits());  //availablePermits可獲取到信號量中還剩余的值  if(s1.availablePermits() < 1 || s2.availablePermits() < 1){  if (s1.availablePermits() < 1) {  log.info("線程【{}】被掛起到信號量【{}】中", id, s1);  //阻塞,并插入到condition1的阻塞隊列中  condition1.await();  } else {  log.info("線程【{}】被掛起到信號量【{}】中", id, s2);  //阻塞,并插入到condition2的阻塞隊列中  condition2.await();  }  log.info("被掛起的線程【{}】被喚醒執(zhí)行。", id);  } else {  log.info("為線程【{}】分配資源!", id);  s1.acquire();  s2.acquire();  }  lock.unlock();  }  public static void Ssignal(Semaphore s1, Semaphore s2) throws InterruptedException {  log.info("線程【{}】執(zhí)行了釋放資源", id);  lock.tryLock(1, TimeUnit.SECONDS);  s1.release();  s2.release();  //喚醒等待隊列中的線程  condition.signal();  lock.unlock();  }

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

2.一個簡單的示例

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

public static void Swait(String id, Semaphore s1, Semaphore s2) throws InterruptedException {  lock.tryLock(1, TimeUnit.SECONDS);  log.info("當(dāng)前的兩個信號量的狀態(tài):【{},{}】", s1.availablePermits(), s2.availablePermits());  //如果申請不到,就掛起線程,并將線程插入到condition的隊列中  while (s1.availablePermits() < 1 || s2.availablePermits() < 1) {  if (s1.availablePermits() < 1) {  log.info("線程【{}】被掛起到信號量【{}】中", id, s1);  condition1.await();  } else {  log.info("線程【{}】被掛起到信號量【{}】中", id, s2);  condition2.await();  }  log.info("被掛起的線程【{}】被喚醒執(zhí)行。", id);  }  log.info("為線程【{}】分配資源!", id);  s1.acquire();  s2.acquire();  lock.unlock();  }

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

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

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

public static void Swait(String id, Semaphore... list) throws InterruptedException {  lock.lock();  //如果資源不足,就掛起線程,并將線程插入到condition的隊列中  while (true) {  int count=0;  //循環(huán)判斷參數(shù)列表中信號量的可用值  for (Semaphore semaphore:list){  if(semaphore.availablePermits()>0){  count++;  }  }  //如果資源都滿足,則跳出循環(huán),進(jìn)行資源分配  if(count == list.length){  break;  }  log.info("線程【{}】被掛起-----", id);  //將當(dāng)前線程阻塞  condition1.await();  log.info("被掛起的線程【{}】被喚醒執(zhí)行。", id);  }  log.info("為線程【{}】分配資源!", id);  //分配資源  for (Semaphore semaphore:list){  semaphore.acquire();  }  lock.unlock();  }  public static void Ssignal(String id, Semaphore... list) throws InterruptedException {  log.info("線程【{}】執(zhí)行了釋放資源", id);  lock.tryLock(1, TimeUnit.SECONDS);  //循環(huán)釋放信號量  for (Semaphore semaphore:list){  semaphore.release();  }  //喚醒等待隊列中的線程  condition.signal();  lock.unlock();  }

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

4.一個完整的例子

這里我們使用一個經(jīng)典的進(jìn)程同步問題來演示我們使用Java模擬的AND型信號量,在這里,我們采用生產(chǎn)者&ndash;消費(fèi)者問題來演示,完整的代碼如下:

//用來保證互斥的訪問臨界區(qū)(緩存區(qū))  static final Semaphore mutex = new Semaphore(1);  //緩沖區(qū),最大容量為50  static List<Integer> buffer = new ArrayList<>();  //緩沖區(qū)中還可放入的消息數(shù)量  static final Semaphore empty = new Semaphore(50);  //緩沖區(qū)中的消息數(shù)量  static final Semaphore full = new Semaphore(0);  //可重入鎖和條件變量  static Lock lock = new ReentrantLock();  static Condition condition = lock.newCondition();  //用與輔助的簡單的生成消息  static Integer count = 0;  //生產(chǎn)者  static class Producer extends Thread {  Producer(String name) {  super.setName(name);  }  @Override  public void run() {  do {  try {  Swait(this.getName(), mutex, empty);  log.info("生產(chǎn)了一條消息:【{}】", count);  buffer.add(count++);  Thread.sleep(1000);  Ssignal(this.getName(), mutex, full);  } catch (InterruptedException e) {  log.error("生產(chǎn)消息時產(chǎn)生異常!");  }  } while (true);  }  }  //消費(fèi)者  static class Consumer extends Thread {  Consumer(String name) {  super.setName(name);  }  @Override  public void run() {  do {  try {  Swait(this.getName(), mutex, full);  log.info("消費(fèi)了一條消息:【{}】", buffer.remove(0));  Thread.sleep(1000);  Ssignal(this.getName(), mutex, empty);  } catch (InterruptedException e) {  log.error("消費(fèi)消息時產(chǎn)生異常!");  }  } while (true);  }  }  public static void Swait(String id, Semaphore... list) throws InterruptedException {  lock.lock();  //如果資源不足,就掛起線程,并將線程插入到condition的隊列中  while (true) {  int count=0;  for (Semaphore semaphore:list){  if(semaphore.availablePermits()>0){  count++;  }  }  if(count == list.length){  break;  }  log.info("線程【{}】被掛起", id);  condition.await();  log.info("被掛起的線程【{}】被喚醒執(zhí)行。", id);  }  log.info("為線程【{}】分配資源!", id);  for (Semaphore semaphore:list){  semaphore.acquire();  }  lock.unlock();  }  public static void Ssignal(String id, Semaphore... list) throws InterruptedException {  log.info("線程【{}】執(zhí)行了釋放資源", id);  lock.tryLock(1, TimeUnit.SECONDS);  for (Semaphore semaphore:list){  semaphore.release();  }  //喚醒等待隊列中的一個線程  condition.signal();  lock.unlock();  }  public static void main(String[] args) {  Producer p1 = new Producer("p1");  Consumer c1 = new Consumer("c1");  p1.start();  c1.start();  }

上面代碼都是可以直接執(zhí)行的,如果不需要使用參數(shù)列表,可以將上面的Swait方法進(jìn)行替換即可(記得創(chuàng)建對應(yīng)的條件變量)。


到此,關(guān)于“JUC怎么模擬AND型信號量”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

網(wǎng)頁名稱:JUC怎么模擬AND型信號量
網(wǎng)頁地址:http://www.chinadenli.net/article30/pgiopo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信公眾號網(wǎng)頁設(shè)計公司軟件開發(fā)App開發(fā)網(wǎng)站維護(hù)企業(yè)網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司