国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

java多線程二之線程同步的三種方法

2019-11-14 21:05:23
字體:
來源:轉載
供稿:網友
java多線程二之線程同步的三種方法

      java多線程的難點是在:處理多個線程同步與并發運行時線程間的通信問題。java在處理線程同步時,常用方法有:

1、synchronized關鍵字。

2、Lock顯示加鎖。

3、信號量Semaphore。

 

線程同步問題引入:

      創建一個銀行賬戶Account類,在創建并啟動100個線程往同一個Account類實例里面添加一塊錢。在沒有使用上面三種方法的情況下:

代碼:

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class AccountWithoutSync {PRivate static Account account = new Account();   //實例化一個賬戶public static void main(String[] args){long start = System.currentTimeMillis();//使用ExecutorService創建線程池ExecutorService executor  = Executors.newCachedThreadPool();for(int i=0;i<100;i++){executor.execute(new AddPennyTask());}//關閉線程池 即使線程池中還有未完成的線程 返回未完成的清單executor.shutdown();//關閉之后還是要保證未完成的線程繼續完成  如果線程池中所有任務都完成了,isTerminated返回truewhile(!executor.isTerminated()){}long end = System.currentTimeMillis();//balance有余額的意思System.out.println("現在賬戶里面的余額是:" + account.getBalance());System.out.println("花費的時間以微秒為單位:"+(end-start)+"微秒");}//這個線程只調用了一個方法public static class AddPennyTask implements Runnable{@Overridepublic void run() {account.deposit(1);}}//一個內部類  用于 賬戶的相關處理public static class Account{private int balance =0;public int getBalance(){return balance;}public  void deposit(int amount){int newBalance = balance + amount;//為了讓錯誤體現的更明顯try {Thread.sleep(4);   //5毫秒} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}balance= newBalance;//其實就是balance +=amount;//不過換成這一段代碼結果就在100和99左右}}}

 

運行截圖df97c06074cc45a383ff66c7b3f9cc66

 

       錯的不是一般的明顯,明明存入了100塊,顯示只有2塊,原因也很簡單,就是100個線程同時對acount進行修改,當第100該線程把錢改成100時,第2個線程最后修改,把它改成了2,這群不聽話的線程,那就好好管管他們吧,讓他們乖乖聽話,在這之前,還是要記住以下一些名詞:

競爭狀態:當多個線程訪問同一公共資源并引發沖突造成線程不同步,我們稱這種狀態為競爭狀態。

線程安全:是針對類來說的,如果一個類的對象在多線程程序中不會導致競爭狀態,我們就稱這類為線程安全的,上面的Account是線性不安全的,而又如StringBuffer是線程安全的,而StringBuilder則是線程不安全的。

 

臨界區:造成競爭狀態的原因是多個線程同時進入了程序中某一特定部分,如上面程序中的deposit方法,我們稱這部分為程序中的臨界區,我們要解決多線程不同步問題,就是要解決如何讓多個線程有序的訪問臨界區

 

使用synchronized關鍵字

1、同步方法:在deposit方法前加synchronized關鍵字,使得該方法變成同步方法:public synchronized void deposit(double amount){}

2、同步語句:對某一代碼塊加synchronized關鍵字,常用格式:

synchronized(exper) {statement}   其中exper是對象的引用,如上面的程序,在要在調用depsoit方法時,改成這樣:  synchronized(account){account.deposit(1);}

      使用synchronized,其實是隱式地給方法或者代碼塊加了鎖,任何同步的實例方法都可以轉換為同步語句:

public synchronized void  method(){}

轉換為同步語句: public  void  method{sysnchronized(this){}}

 

利用lock加鎖同步

       java也可以用Lock顯示的對臨界區代碼加鎖以及解鎖,這比用synchronized關鍵字更加直觀靈活

       一個鎖是一個Lock接口的實例,該接口定義了加鎖解鎖的方法,且一個鎖可以多次調用其newCondition()方法創建名為Condition對象的實例,以此進行線程間的通信(在后面用到)。

     有了Lock接口,我們還要實現它,java提供了RenentrantLock類,該類是為創建相互排斥鎖而實現了Lock接口,由此就好辦了,下面看一下書上的圖:

image

代碼如下:

public static class Account2{private static Lock lock = new ReentrantLock();private int balance =0;public int getBalance(){return balance;}public  void deposit(int amount){lock.lock();try{int newBalance = balance + amount;Thread.sleep(4);   balance= newBalance;}catch (InterruptedException e) {e.printStackTrace();}finally{lock.unlock();}}}

 

給個運行截圖image

         100塊存入,且時間明顯比之前久了,100個線程都乖乖的排隊訪問臨界區。另外注意在對lock()的調用后,緊跟隨try catch finnaly語句,這是個好習慣

 

利用信號量同步

            信號量是個好東西,信號量機制在操作系統方面有著廣泛的應用,如linux進程同步信號量,而在java里,Semaphore包包含了一些訪問信號量的方法。

信號量可以用來限制訪問共享資源的線程數,在訪問臨界區資源前,線程必須獲取一個信號量,在訪問完之后返回一個信號量。下圖是關于類Semaphore,該類包含訪問信號量的方法:

`ES0J3D(F35DDQ$G~4BGX%I

利用信號量Semaphorre,可以將上面的Account類改成這樣:

public static class Account
{private static Semaphore semaphore = new Semaphore(1);  //創建一個信號量private int balance =0;public int getBalance(){return balance;}public  void deposit(int amount){try {semaphore.acquire();int newBalance = balance + amount;Thread.sleep(4);   balance= newBalance;} catch (InterruptedException e) {e.printStackTrace();}finally{semaphore.release();   //返回一個信號量}}}

 

      網上有很多關于java多線程的文章,有不少寫成系列的,但個人覺得像多線程這么有有意思的部分,還是得好好靜下心來品位,上面的三種方法,可以解決多線程同步問題,后面還會繼續學習,嗯,加油。

     本文出自于博客園蘭幽,轉載請說明出處。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 育儿| 乌拉特中旗| 江北区| 雅安市| 高陵县| 攀枝花市| 兴城市| 南宁市| 桦甸市| 河池市| 陆良县| 沙洋县| 洪雅县| 贞丰县| 兰坪| 兴国县| 裕民县| 灵宝市| 星子县| 哈巴河县| 安康市| 双城市| 永嘉县| 阆中市| 正宁县| 苏州市| 丹巴县| 太谷县| 新丰县| 武胜县| 连州市| 陕西省| 贵德县| 应用必备| 北宁市| 兴仁县| 麻阳| 河南省| 普定县| 台东县| 宁阳县|