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

          Java多線程之StampedLock

          共 1139字,需瀏覽 3分鐘

           ·

          2021-12-13 15:39

          這里就JUC包中的StampedLock做相關(guān)介紹

          abstract.jpeg

          概述

          在讀多寫(xiě)少的場(chǎng)景下,非常適合使用ReentrantReadWriteLock讀寫(xiě)鎖。但其也存在一定的弊端,其有可能導(dǎo)致寫(xiě)線程饑餓。為此JDK 8中提供了StampedLock類,其是一個(gè)非公平的讀寫(xiě)鎖。其與ReentrantReadWriteLock相比,不僅提供了傳統(tǒng)意義上的悲觀讀鎖和寫(xiě)鎖,最大的區(qū)別是其還為讀操作提供了樂(lè)觀鎖的方法——即所謂的樂(lè)觀讀鎖。當(dāng)然其也有弊端,無(wú)論是悲觀讀鎖還是寫(xiě)鎖,均不支持條件變量Condition;然后從類名也可以看到其是不可重入鎖。需要注意的是,雖然一個(gè)線程可以多次獲取悲觀讀鎖,但究其原因是因?yàn)楸^讀鎖是共享鎖。實(shí)際實(shí)踐中,可以直接通過(guò)writeLock、readLock等阻塞式 或 tryWriteLock、tryReadLock等非阻塞式的方式獲取鎖,也可通過(guò)ReadLockView讀鎖視圖、WriteLockView寫(xiě)鎖視圖、ReadWriteLockView讀寫(xiě)鎖視圖來(lái)進(jìn)行相應(yīng)鎖的操作

          基本實(shí)踐

          讀鎖、寫(xiě)鎖

          這里就基本的悲觀讀鎖、寫(xiě)鎖的使用進(jìn)行實(shí)踐,示例如下所示

          @FixMethodOrder(MethodSorters.NAME_ASCENDING)
          public?class?StampedLockTest1?{

          ????private?static?DateTimeFormatter?formatter?=?DateTimeFormatter.ofPattern("HH:mm:ss.SSS");

          ????private?static?ExecutorService?threadPool?=?Executors.newFixedThreadPool(10);

          ????private?static?StampedLock?stampedLock?=?new?StampedLock();

          ????private?static?Integer?count;

          ????/**
          ?????*?測(cè)試:?讀鎖為共享鎖
          ?????*/

          ????@Test
          ????public?void?test1()?{
          ????????System.out.println("\n----------------------?Test?1?----------------------");

          ????????count?=?100;
          ????????for(int?i=1;?i<5;?i++)?{
          ????????????Runnable?runnable?=?new?ReadTask("Task"+i);
          ????????????threadPool.execute(?runnable?);
          ????????}

          ????????//?主線程等待所有任務(wù)執(zhí)行完畢
          ????????try{?Thread.sleep(?10*1000?);?}?catch?(Exception?e)?{}
          ????}

          ????/**
          ?????*?測(cè)試:?寫(xiě)鎖為獨(dú)占鎖
          ?????*/

          ????@Test
          ????public?void?test2()?{
          ????????System.out.println("\n----------------------?Test?2?----------------------");

          ????????count?=?200;
          ????????for(int?i=1;?i<5;?i++)?{
          ????????????Runnable?runnable?=?new?WriteTask("Task"+i);
          ????????????threadPool.execute(?runnable?);
          ????????}

          ????????//?主線程等待所有任務(wù)執(zhí)行完畢
          ????????try{?Thread.sleep(?10*1000?);?}?catch?(Exception?e)?{}
          ????}

          ????/**
          ?????*?測(cè)試:?讀寫(xiě)互斥
          ?????*/

          ????@Test
          ????public?void?test3()?{
          ????????System.out.println("\n----------------------?Test?3?----------------------");

          ????????count?=?300;
          ????????for(int?i=1;?i<9;?i++)?{
          ????????????Runnable?task?=?null;
          ????????????Boolean?isReadTask?=?RandomUtils.nextBoolean();
          ????????????if(?isReadTask?)?{
          ????????????????task?=?new?ReadTask2("讀任務(wù)?#"+i);
          ????????????}?else?{
          ????????????????task?=?new?WriteTask2("寫(xiě)任務(wù)?#"+i);
          ????????????}
          ????????????threadPool.execute(?task?);
          ????????}
          ????????//?主線程等待所有任務(wù)執(zhí)行完畢
          ????????try{?Thread.sleep(?20*1000?);?}?catch?(Exception?e)?{}
          ????}

          ????/**
          ?????*?打印信息
          ?????*?@param?msg
          ?????*/

          ????public?static?void?info(String?msg)?{
          ????????String?time?=?formatter.format(LocalTime.now());
          ????????String?log?=?"["+time+"]?"?+?msg;
          ????????System.out.println(log);
          ????}

          ????@AllArgsConstructor
          ????private?static?class?ReadTask?implements?Runnable?{

          ????????private?String?taskName;

          ????????@Override
          ????????public?void?run()?{
          ????????????Integer?localData?=?null;
          ????????????long?stamp?=?stampedLock.readLock();
          ????????????try{
          ????????????????info(taskName?+?":?成功獲取讀鎖,?stamp:?"?+?stamp);
          ????????????????localData?=?count;
          ????????????}?catch?(Exception?e)?{
          ????????????????info(taskName+"Happen?Exception");
          ????????????}?finally?{
          ????????????????info(taskName?+?":?釋放讀鎖,?stamp:?"+stamp+",?localData:?"+localData);
          ????????????????stampedLock.unlockRead(stamp);
          ????????????}
          ????????}
          ????}

          ????@AllArgsConstructor
          ????private?static?class?WriteTask?implements?Runnable?{

          ????????private?String?taskName;

          ????????@Override
          ????????public?void?run()?{
          ????????????long?stamp?=?stampedLock.writeLock();
          ????????????try?{
          ????????????????info(taskName?+?":?成功獲取寫(xiě)鎖,?stamp:?"?+?stamp);
          ????????????????count++;
          ????????????}?catch?(Exception?e)?{
          ????????????????info(taskName+"Happen?Exception");
          ????????????}?finally?{
          ????????????????info(taskName?+?":?釋放寫(xiě)鎖,?stamp:?"+stamp+",?count:?"?+?count);
          ????????????????stampedLock.unlockWrite(stamp);
          ????????????}
          ????????}
          ????}

          ????@AllArgsConstructor
          ????private?static?class?ReadTask2?implements?Runnable?{

          ????????private?String?taskName;

          ????????@Override
          ????????public?void?run()?{
          ????????????Integer?localData?=?null;
          ????????????Lock?readLock?=?stampedLock.asReadLock();
          ????????????readLock.lock();
          ????????????try{
          ????????????????info(taskName?+?":?成功獲取讀鎖");
          ????????????????localData?=?count;
          ????????????}?catch?(Exception?e)?{
          ????????????????info(taskName+"Happen?Exception");
          ????????????}?finally?{
          ????????????????info(taskName?+?":?釋放讀鎖,?localData:?"+localData+"\n");
          ????????????????readLock.unlock();
          ????????????}
          ????????}
          ????}

          ????@AllArgsConstructor
          ????private?static?class?WriteTask2?implements?Runnable?{

          ????????private?String?taskName;

          ????????@Override
          ????????public?void?run()?{
          ????????????Lock?writeLock?=?stampedLock.asWriteLock();
          ????????????writeLock.lock();
          ????????????try?{
          ????????????????info(taskName?+?":?成功獲取寫(xiě)鎖");
          ????????????????count++;
          ????????????}?catch?(Exception?e)?{
          ????????????????info(taskName+"Happen?Exception");
          ????????????}?finally?{
          ????????????????info(taskName?+?":?釋放寫(xiě)鎖,?count:?"?+?count?+"\n");
          ????????????????writeLock.unlock();
          ????????????}
          ????????}
          ????}
          }

          測(cè)試結(jié)果如下所示,符合預(yù)期

          figure 1.jpeg

          可以看到StampedLock獲取鎖、釋放鎖都需要相應(yīng)的stamp值。為此也可以通過(guò)相應(yīng)的視圖類進(jìn)行操作,如上述代碼的test3所示。其相應(yīng)測(cè)試結(jié)果所示。可以看到悲觀讀鎖是一個(gè)共享鎖,而寫(xiě)鎖則是一個(gè)互斥鎖

          figure 2.jpeg

          樂(lè)觀讀鎖

          可通過(guò)tryOptimisticRead獲取一個(gè)stamp,即所謂的樂(lè)觀讀鎖。然后在完成讀操作后,通過(guò)validate方法對(duì)stamp進(jìn)行檢查。由于讀過(guò)程通常是非原子性的,故需要判斷是否存在其他線程在此期間獲取到了寫(xiě)鎖,對(duì)數(shù)據(jù)進(jìn)行了修改。造成當(dāng)前線程讀取的數(shù)據(jù)狀態(tài)不一致(部分為修改前的,部分為修改后的)。如果在當(dāng)前線程進(jìn)行讀的過(guò)程中發(fā)生了修改更新,則檢查結(jié)果為false。這時(shí)再獲取悲觀讀鎖進(jìn)行重讀。事實(shí)上,由于樂(lè)觀讀鎖并沒(méi)有鎖。故其一方面不會(huì)阻塞寫(xiě)線程獲取寫(xiě)鎖,也不需要在結(jié)束后釋放該鎖。示例代碼如下所示

          public?class?StampedLockTest2?{

          ????private?static?DateTimeFormatter?formatter?=?DateTimeFormatter.ofPattern("HH:mm:ss.SSS");

          ????private?static?ExecutorService?threadPool?=?Executors.newFixedThreadPool(10);

          ????private?static?StampedLock?stampedLock?=?new?StampedLock();

          ????private?static?Integer?count;

          ????/**
          ?????*?測(cè)試:?樂(lè)觀讀鎖
          ?????*/

          ????@Test
          ????public?void?test1()?{
          ????????count?=?500;

          ????????threadPool.execute(?new?ReadTask("讀任務(wù)?#1",0)?);
          ????????threadPool.execute(?new?ReadTask("讀任務(wù)?#2",0)?);
          ????????threadPool.execute(?new?ReadTask("讀任務(wù)?#33",2*1000)?);
          ????????threadPool.execute(?new?ReadTask("讀任務(wù)?#44",2*1000)?);

          ????????try{?Thread.sleep(?1000?);?}?catch?(Exception?e)?{}
          ????????threadPool.execute(?new?WriteTask("寫(xiě)任務(wù)?#55")?);

          ????????//?主線程等待所有任務(wù)執(zhí)行完畢
          ????????try{?Thread.sleep(?20*1000?);?}?catch?(Exception?e)?{}
          ????}

          ????/**
          ?????*?打印信息
          ?????*?@param?msg
          ?????*/

          ????public?static?void?info(String?msg)?{
          ????????String?time?=?formatter.format(LocalTime.now());
          ????????String?log?=?"["+time+"]?"?+?msg;
          ????????System.out.println(log);
          ????}

          ????@AllArgsConstructor
          ????private?static?class?ReadTask?implements?Runnable?{

          ????????private?String?taskName;

          ????????private?Integer?sleepTime;

          ????????@Override
          ????????public?void?run()?{
          ????????????long?stamp?=?stampedLock.tryOptimisticRead();
          ????????????info(taskName?+?":?成功獲取樂(lè)觀讀鎖,?stamp:?"+stamp);
          ????????????//?讀取數(shù)據(jù)
          ????????????Integer?localData?=?count;
          ????????????//?模擬業(yè)務(wù)耗時(shí)
          ????????????try{?Thread.sleep(sleepTime);?}?catch?(Exception?e)?{}
          ????????????info(taskName?+?":localData:?"+localData);

          ????????????//?檢查在獲取樂(lè)觀鎖后,?是否被寫(xiě)鎖獲得過(guò)
          ????????????if(?!stampedLock.validate(stamp)?)?{
          ????????????????info(taskName+":?數(shù)據(jù)被其他線程修改需重讀");
          ????????????????stamp?=?stampedLock.readLock();
          ????????????????info(taskName?+?":?成功獲取讀鎖,?stamp:?"?+?stamp);
          ????????????????try{
          ????????????????????//?模擬業(yè)務(wù)耗時(shí)
          ????????????????????try{?Thread.sleep(500);?}?catch?(Exception?e)?{}
          ????????????????}?catch?(Exception?e)?{
          ????????????????????info(taskName+"Happen?Exception");
          ????????????????}?finally?{
          ????????????????????info(taskName?+?":?釋放讀鎖,?stamp:?"+stamp+",?count:?"?+?count+"\n");
          ????????????????????stampedLock.unlockRead(stamp);
          ????????????????}
          ????????????}
          ????????}
          ????}

          ????@AllArgsConstructor
          ????private?static?class?WriteTask?implements?Runnable?{

          ????????private?String?taskName;

          ????????@Override
          ????????public?void?run()?{
          ????????????long?stamp?=?stampedLock.writeLock();
          ????????????try?{
          ????????????????info(taskName?+?":?成功獲取寫(xiě)鎖,?stamp:?"?+?stamp);
          ????????????????count++;
          ????????????}?catch?(Exception?e)?{
          ????????????????info(taskName+"Happen?Exception");
          ????????????}?finally?{
          ????????????????info(taskName?+?":?釋放寫(xiě)鎖,?stamp:?"+stamp+",?count:?"?+?count?+"\n");
          ????????????????stampedLock.unlockWrite(stamp);
          ????????????}
          ????????}
          ????}
          }

          測(cè)試結(jié)果如下所示

          figure 3.jpeg

          參考文獻(xiàn)

          1. Java并發(fā)編程之美 翟陸續(xù)、薛賓田著
          瀏覽 49
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  黄页网站在线观看 | 免费看黄色做爱视频 | 黄色片在线观看网址 | 成人电影三区 | C逼毛片 操她在线 |