<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>

          多線程之讀寫鎖

          共 8316字,需瀏覽 17分鐘

           ·

          2021-07-13 00:55

          前言

          java中,鎖lock是多線程編程的一個(gè)重要組件,可以說凡是涉及到多線程編程,線程安全這一塊就無法避開lock,進(jìn)一步說就是所有的線程安全都是基于鎖實(shí)現(xiàn)的,只是從形式上分為隱式鎖和顯式鎖,synchronized就屬于隱式鎖,像我們之前分享的可重入鎖就屬于顯式鎖,當(dāng)然顯示鎖還有很多,我們今天就來看一個(gè)很常用的顯式鎖——讀寫鎖。

          讀寫鎖

          讀寫鎖是一對互斥鎖,分為讀鎖和寫鎖。讀鎖和寫鎖互斥,讓一個(gè)線程在進(jìn)行讀操作時(shí),不允許其他線程的寫操作,但是不影響其他線程的讀操作;當(dāng)一個(gè)線程在進(jìn)行寫操作時(shí),不允許任何線程進(jìn)行讀操作或者寫操作。

          簡單來說就是,寫鎖會(huì)排斥讀和寫,但是讀鎖只排斥寫,這樣的好處就很明顯,在讀多寫少的應(yīng)用場景下,比其他互斥鎖性能要好很多。下面我們通過一段代碼說明:

          public class Example {
              private static final ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
              private static AtomicInteger count = new AtomicInteger(0);

              public static void main(String[] args) {
                  ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
                  ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();
                  ExecutorService executorService = Executors.newCachedThreadPool();

                  // 寫操作1:寫鎖
                  executorService.execute(() -> {
                      writeLock.lock();
                      for (int i = 0; i < 5; i++) {
                          try {
                              Thread.sleep(1000);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          System.out.println("寫count1: " + count.incrementAndGet());
                      }
                      writeLock.unlock();
                  });
                  // 讀操作1:讀鎖
                  executorService.execute(() -> {
                      readLock.lock();
                      for (int i = 0; i < 5; i++) {
                          try {
                              Thread.sleep(500);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          System.out.println("讀count1: " + count.get());
                      }
                      readLock.unlock();
                  });
                  // 讀操作2:讀鎖
                  executorService.execute(() -> {
                      readLock.lock();
                      for (int i = 0; i < 5; i++) {
                          try {
                              Thread.sleep(200);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          System.out.println("讀count2: " + count.get());
                      }
                      readLock.unlock();
                  });
                  // 寫操作2:寫鎖
                  executorService.execute(() -> {
                      writeLock.lock();
                      for (int i = 0; i < 5; i++) {
                          try {
                              Thread.sleep(100);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          System.out.println("寫count2: " + count.incrementAndGet());
                      }
                      writeLock.unlock();
                  });
                  // 寫操作3:寫鎖
                  executorService.execute(() -> {
                      writeLock.lock();
                      for (int i = 0; i < 5; i++) {
                          System.out.println("寫count3: " + count.incrementAndGet());
                      }
                      writeLock.unlock();
                  });

                  executorService.shutdown();

              }
          }

          上面的代碼中,我們分別有3次寫操作,2次讀操作,然后運(yùn)行上面的代碼:

          運(yùn)行結(jié)果圖片上我們已經(jīng)標(biāo)注了線程休眠情況,根據(jù)運(yùn)行結(jié)果雖然寫count1休眠了1000,讀count1休眠了500,但因?yàn)閷戞i的存在,排斥了其他讀寫操作,讀只能等寫鎖釋放,所以是先寫后讀,也就是寫鎖排斥讀;

          count2休眠了200,讀count1休眠了500,雖然加了讀鎖,但結(jié)果還是讀count2先運(yùn)行,而且期間是讀count1和讀count2交替運(yùn)行,說明讀并不排斥讀,而且讀后面的寫count2只休眠了100,但還是在讀count1和讀count2之后運(yùn)行,說明讀排斥寫;

          count2休眠100,寫count3未休眠,但是寫count3依然在寫count2之后執(zhí)行,說明寫鎖排斥寫。

          綜上,我們在示例中分別證明了我們上面的結(jié)論:寫鎖會(huì)排斥讀和寫,但是讀鎖只排斥寫。

          總結(jié)

          讀寫鎖相比于其他互斥鎖,優(yōu)點(diǎn)很明顯,也就是前面我們說的:在讀多寫少的應(yīng)用場景下,比其他互斥鎖性能要好很多。至于原因,我們也通過示例證明了:寫鎖會(huì)排斥讀和寫,但是讀鎖只排斥寫。

          關(guān)于讀寫鎖,我覺得今天分享的內(nèi)容已經(jīng)比較詳細(xì),不僅展示了它的基本用法,同時(shí)還通過示例反證了它的互斥原則,所以如果你看明白了今天的內(nèi)容,那么互斥鎖這一款的知識你就掌握了。好了,今天的內(nèi)容就到這里吧!

          - END -


          瀏覽 31
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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在线观看 | 国产高清色情 | 手机免费看国产黄色电影 | 九九亚洲视频 |