<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # [synchronized 與 Lock 的那點事](http://www.cnblogs.com/benshan/p/3551987.html) [TOC=1,2] 最近在做一個監控系統,該系統主要包括對數據實時分析和存儲兩個部分,由于并發量比較高,所以不可避免的使用到了一些并發的知識。為了實現這些要求,后臺使用一個隊列作為緩存,對于請求只管往緩存里寫數據。同時啟動一個線程監聽該隊列,檢測到數據,立即請求調度線程,對數據進行處理。 具體的使用方案就是使用同步保證數據的正常,使用線程池提高效率。 同步的實現當然是采用鎖了,java中使用鎖的兩個基本工具是 synchronized 和 Lock。 一直很喜歡synchronized,因為使用它很方便。比如,需要對一個方法進行同步,那么只需在方法的簽名添加一個synchronized關鍵字。 // 未同步的方法 public void test() {} // 同步的方法 pubilc synchronized void test() {} synchronized 也可以用在一個代碼塊上,看 public void test() { ? ? ?synchronized(obj) { ? ? ? ? ? System.out.println("==="); ?????} } synchronized 用在方法和代碼塊上有什么區別呢? synchronized 用在方法簽名上(以test為例),當某個線程調用此方法時,會獲取該實例的對象鎖,方法未結束之前,其他線程只能去等待。當這個方法執行完時,才會釋放對象鎖。其他線程才有機會去搶占這把鎖,去執行方法test,但是發生這一切的基礎應當是所有線程使用的同一個對象實例,才能實現互斥的現象。否則synchronized關鍵字將失去意義。 (**但是如果該方法為類方法,即其修飾符為static,那么synchronized 意味著某個調用此方法的線程當前會擁有該類的鎖,只要該線程持續在當前方法內運行,其他線程依然無法獲得方法的使用權!**) synchronized 用在代碼塊的使用方式:synchronized(obj){//todo code here} 當線程運行到該代碼塊內,就會擁有obj對象的對象鎖,如果多個線程共享同一個Object對象,那么此時就會形成互斥!特別的,當obj == this時,表示當前調用該方法的實例對象。即 public void test() { ?????... ?????synchronized(this) { ? ? ??????// todo your code ?????} ?????... } 此時,其效果等同于 public synchronized void test() { ? ? ?// todo?your code } 使用synchronized代碼塊,可以只對需要同步的代碼進行同步,這樣可以大大的提高效率。 小結: 使用synchronized 代碼塊相比方法有兩點優勢: 1、可以只對需要同步的使用 2、與wait()/notify()/nitifyAll()一起使用時,比較方便 ---------------------------------------------------------------------------------------------------------------------------------------------------------- wait() 與notify()/notifyAll() **這三個方法都是Object的方法,并不是線程的方法!** wait():釋放占有的對象鎖,線程進入等待池,釋放cpu,而其他正在等待的線程即可搶占此鎖,獲得鎖的線程即可運行程序。而sleep()不同的是,線程調用此方法后,會休眠一段時間,休眠期間,會暫時釋放cpu,但并不釋放對象鎖。也就是說,在休眠期間,其他線程依然無法進入此代碼內部。休眠結束,線程重新獲得cpu,執行代碼。**wait()和sleep()最大的不同在于wait()會釋放對象鎖,而sleep()不會!** notify(): 該方法會喚醒因為調用對象的wait()而等待的線程,其實就是**對對象鎖的喚醒,從而使得wait()的線程可以有機會獲取對象鎖**。調用notify()后,并不會立即釋放鎖,而是繼續執行當前代碼,直到synchronized中的代碼全部執行完畢,才會釋放對象鎖。JVM則會在等待的線程中調度一個線程去獲得對象鎖,執行代碼。需要注意的是,**wait()和notify()必須在synchronized代碼塊中調用**。 notifyAll()則是喚醒所有等待的線程。 為了說明這一點,舉例如下: 兩個線程依次打印"A""B",總共打印10次。 **public**?**class**?Consumer?**implements**?Runnable { ? ?????@Override ?????**public**?**synchronized**?**void**?run() { ????????????//?**TODO**?Auto-generated method stub ????????????**int**?count = 10; ????????????**while**(count > 0) { ?????????????????**synchronized**?(Test.?*obj*) { ????????????????????? ?????????????????????System.?*out*.print(?"B"); ?????????????????????count --; ?????????????????????Test.?*obj*.notify();?// 主動釋放對象鎖 ????????????????????? ??????????????????????**try**?{ ???????????????????????????Test.?*obj*.wait(); ??????????????????????????? ?????????????????????}?**catch**?(InterruptedException e) { ????????????????????????????//?**TODO**?Auto-generated catch block ???????????????????????????e.printStackTrace(); ?????????????????????} ????????????????} ???????????????? ???????????} ?????} } **public**?**class**?Produce?**implements**?Runnable { ? ?????@Override ?????**public**?**void**?run() { ????????????//?**TODO**?Auto-generated method stub ????????????**int**?count = 10; ????????????**while**(count > 0) { ?????????????????**synchronized**?(Test.?*obj*) { ????????????????????? ??????????????????????//System.out.print("count = " + count); ?????????????????????System.?*out*.print(?"A"); ?????????????????????count --; ?????????????????????Test.?*obj*.notify(); ????????????????????? ??????????????????????**try**?{ ???????????????????????????Test.?*obj*.wait(); ?????????????????????}?**catch**?(InterruptedException e) { ????????????????????????????//?**TODO**?Auto-generated catch block ???????????????????????????e.printStackTrace(); ?????????????????????} ????????????????} ???????????????? ???????????} ? ?????} ? } ? 測試類如下: **public**?**class**?Test { ? ?????**public**?**static**?**final**?Object?*obj*?=?**new**?Object(); ????? ?????**public**?**static**?**void**?main(String[] args) { ??????????? ????????????**new**?Thread(?**new**?Produce()).start(); ????????????**new**?Thread(?**new**?Consumer()).start(); ??????????? ?????} } ? 這里使用static obj作為鎖的對象,當線程Produce啟動時(假如Produce首先獲得鎖,則Consumer會等待),打印“A”后,會先主動釋放鎖,然后阻塞自己。Consumer獲得對象鎖,打印“B”,然后釋放鎖,阻塞自己,那么Produce又會獲得鎖,然后...一直循環下去,直到count = 0.這樣,使用Synchronized和wait()以及notify()就可以達到線程同步的目的。 ---------------------------------------------------------------------------------------------------------------------------------------------------------- **除了wait()和notify()協作完成線程同步之外,使用Lock也可以完成同樣的目的。** ReentrantLock 與synchronized有相同的并發性和內存語義,還包含了中斷鎖等候和定時鎖等候,意味著線程A如果先獲得了對象obj的鎖,那么線程B可以在等待指定時間內依然無法獲取鎖,那么就會自動放棄該鎖。 但是由于synchronized是在JVM層面實現的,因此系統可以監控鎖的釋放與否,而ReentrantLock使用代碼實現的,系統無法自動釋放鎖,需要在代碼中finally子句中顯式釋放鎖lock.unlock(); 同樣的例子,使用lock 如何實現呢? **public**?**class**?Consumer?**implements**?Runnable { ? ?????**private**?Lock?lock; ?????**public**?Consumer(Lock lock) { ????????????**this**.?lock?= lock; ?????} ?????@Override ?????**public**?**void**?run() { ????????????//?**TODO**?Auto-generated method stub ????????????**int**?count = 10; ????????????**while**( count > 0 ) { ?????????????????**try**?{ ??????????????????????lock.lock(); ?????????????????????count --; ?????????????????????System.?*out*.print(?"B"); ????????????????}?**finally**?{ ??????????????????????lock.unlock(); //主動釋放鎖 ??????????????????????**try**?{ ???????????????????????????Thread.?*sleep*(91L); ?????????????????????}?**catch**?(InterruptedException e) { ????????????????????????????//?**TODO**?Auto-generated catch block ???????????????????????????e.printStackTrace(); ?????????????????????} ????????????????} ???????????} ? ?????} ? } **public**?**class**?Producer?**implements**?Runnable{ ? ?????**private**?Lock?lock; ?????**public**?Producer(Lock lock) { ????????????**this**.?lock?= lock; ?????} ?????@Override ?????**public**?**void**?run() { ????????????//?**TODO**?Auto-generated method stub ????????????**int**?count = 10; ????????????**while**?(count > 0) { ?????????????????**try**?{ ??????????????????????lock.lock(); ?????????????????????count --; ?????????????????????System.?*out*.print(?"A"); ????????????????}?**finally**?{ ??????????????????????lock.unlock(); ??????????????????????**try**?{ ???????????????????????????Thread.?*sleep*(90L); ?????????????????????}?**catch**?(InterruptedException e) { ????????????????????????????//?**TODO**?Auto-generated catch block ???????????????????????????e.printStackTrace(); ?????????????????????} ????????????????} ???????????} ?????} } ? 調用代碼: **public**?**class**?Test { ? ?????**public**?**static**?**void**?main(String[] args) { ???????????Lock lock =?**new**?ReentrantLock(); ??????????? ???????????Consumer consumer =?**new**?Consumer(lock); ???????????Producer?producer?=?**new**?Producer(lock); ??????????? ????????????**new**?Thread(consumer).start(); ????????????**new**?Thread(?producer).start(); ??????????? ?????} } 使用建議: 在并發量比較小的情況下,使用synchronized是個不錯的選擇,但是在并發量比較高的情況下,其性能下降很嚴重,此時ReentrantLock是個不錯的方案。 --------------------------------------------------------------------------------------------------------------------------------------
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看