亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

Java中synchronized和Lock實現并發鎖

2019-11-06 06:27:05
字體:
來源:轉載
供稿:網友

前言

參考文章: 1. java 多線程:synchronized 關鍵字用法(修飾類,方法,靜態方法,代碼塊) 2. Java 多線程:Lock 接口(接口方法分析,ReentrantLock,ReadWriteLock) 3. synchronized 與 Lock 的那點事 4. Java并發編程:Lock 5. ReentrantLock(重入鎖)以及公平性 參考書籍:《瘋狂Java講義(第二版)》。

synchronized

  創建一個賬戶類Account,有姓名和賬戶余額屬性以及get、set方法:

public class Account { PRivate String name; private double money; public Account(String name, double money) { super(); this.name = name; this.money = money; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getMoney() { return money; } public void setMoney(double money) { this.money = money; }}

  線程類是實現Runnable接口的Bank類,代碼如下:

public class Bank implements Runnable { private Account account; private double getMoney; // 本次取錢數量 public Bank(Account account, double getMoney) { super(); this.account = account; this.getMoney = getMoney; } @Override public void run() { getMoney(); } private void getMoney() { if (account.getMoney() >= getMoney) { System.out.println("取錢成功!取出:" + getMoney + " 元!"); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } account.setMoney(account.getMoney() - getMoney); System.out.println(account.getName() + "賬戶余額為:" + account.getMoney() + " 元!"); } else { System.out.println("取錢失敗,余額不足!"); } }}

  main函數如下:

public class Test { public static void main(String[] args) { Account account = new Account("Rojer", 2000); Bank bank = new Bank(account, 1200); new Thread(bank).start(); new Thread(bank).start(); }}

  運行結果如下:

取錢成功!取出:1200.0 元!取錢成功!取出:1200.0 元!Rojer賬戶余額為:800.0 元!Rojer賬戶余額為:800.0 元!

  從結果中看出,兩個線程都取錢成功了,這樣銀行是會虧死的,現在要實現一個時間段內只能有一個線程執行取錢操作,可以用synchronized關鍵字來進行加鎖。

修飾方法

  注意,synchronized不能修飾接口中的方法,而且父類中的synchronized方法被子類繼承以后,是沒有繼承synchronized的,如果要使用,還需要加上synchronized關鍵字。   用synchronized關鍵字來修飾Bank類的getMoney方法:

private synchronized void getMoney() { if (account.getMoney() >= getMoney) { System.out.println("取錢成功!取出:" + getMoney + " 元!"); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } account.setMoney(account.getMoney() - getMoney); System.out.println(account.getName() + "賬戶余額為:" + account.getMoney() + " 元!"); } else { System.out.println("取錢失敗,余額不足!"); } }

  運行結果如下:

取錢成功!取出:1200.0 元!Rojer賬戶余額為:800.0 元!取錢失敗,余額不足!

  可以看出程序運行結果和我們期待的一樣,只有一個線程取錢成功,第二個線程取錢的時候失敗了,因為余額不足。   用synchronized修飾方法時,所有的synchronized修飾的方法都被鎖住了,只能供當前擁有鎖的線程使用,但是其他的非synchronized修飾的方法沒有被鎖住,是可以正常調用的。HashTable中就是這樣實現線程安全的,可以參考我的另一篇文章-深入JDK源碼之Hashtable。所以說,用synchronized來修飾方法是重量級的。

修飾代碼塊

  修飾代碼塊就是以下面的方式,用synchronized關鍵字“包裹”住要同步的代碼塊:

synchronized (...) { ...}

  括號中可以是一個對象,也可以是一個類的class。如果是一個對象的話,那么只對該對象的線程進行加鎖,如果是修飾了一個類的class,如上文的Bank.class,那么無論有多少個Bank對象,并發時只能有一個對象的一個線程訪問同步代碼塊,其他線程都要等待,但是訪問沒有synchronized鎖住的代碼塊不受影響。

鎖住class

  修改getMoney代碼如下所示:

private void getMoney() { synchronized (Bank.class) { if (account.getMoney() >= getMoney) { System.out.println("取錢成功!取出:" + getMoney + " 元!"); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } account.setMoney(account.getMoney() - getMoney); System.out.println(account.getName() + "賬戶余額為:" + account.getMoney() + " 元!"); } else { System.out.println("取錢失敗,余額不足!"); } } }

  執行程序結果如下:

取錢成功!取出:1200.0 元!Rojer賬戶余額為:800.0 元!取錢失敗,余額不足!

鎖住對象

  修改getMoney代碼,鎖住賬戶account對象,如下所示:

private void getMoney() { synchronized (account) { if (account.getMoney() >= getMoney) { System.out.println("取錢成功!取出:" + getMoney + " 元!"); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } account.setMoney(account.getMoney() - getMoney); System.out.println(account.getName() + "賬戶余額為:" + account.getMoney() + " 元!"); } else { System.out.println("取錢失敗,余額不足!"); } }}

  運行結果如下:

取錢成功!取出:1200.0 元!Rojer賬戶余額為:800.0 元!取錢失敗,余額不足!

  synchronized修飾的是私有的account對象,因此當前對象的其他線程如果要使用account對象,就必須先拿到對象的鎖才可以。   相比于synchronized修飾方法,修飾代碼段的同步粒度更小,更加輕量。

修飾靜態方法

  靜態方法是所有類的對象共享的,因此用synchronized修飾靜態方法,其實就是修飾類,即一個線程擁有該靜態方法的監視器的時候,其他所有該類的對象,或者直接調用該靜態方法的線程,都需要等待當前線程釋放監視器。

Lock

  從 Java 5 開始,Java提供了一種更為強大的線程同步機制——通過顯示定義同步鎖對象來實現同步,在這種機制下,同步鎖由Lock對象充當。   Lock提供了比synchronized方法和synchronized代碼塊更廣泛的鎖定操作,Lock允許實現更靈活的結構,可以具有差別很大的屬性,并且支持多個相關的Condition對象。

—瘋狂Java講義

Lock接口

  Lockjava.util.concurrent.locks包中的一個接口,源碼如下:

public interface Lock { // 用來獲取鎖,如果鎖已被其他線程獲取,則進行等待。 void lock(); // 如果獲取鎖成功返回true,否則返回false boolean tryLock(); // 拿不到鎖時會等待一定的時間,在時間期限之內如果還拿不到鎖,就返回false。 // 如果如果一開始拿到鎖或者在等待期間內拿到了鎖,則返回true boolean tryLock(long time, TimeUnit unit) throws InterruptedException; // 通過這個方法去獲取鎖時,如果線程正在等待獲取鎖,則這個線程能夠響應中斷,即中斷線程的等待狀態 void lockInterruptibly() throws InterruptedException; // 釋放鎖 void unlock(); Condition newCondition();}

  ReentrantLock(可重入鎖)是Lock接口的實現類,可重入,也就是可以在當前線程上對資源再加一個鎖,相應的有一個值在記錄加了幾重鎖,如果釋放鎖時沒有釋放完,則會報錯。同時,ReentrantLock有個特性就是公平性,這個后面再說。

ReadWriteLock接口

  還有一個接口ReadWriteLock,顧名思義是讀寫鎖:

public interface ReadWriteLock { /** * Returns the lock used for reading. * * @return the lock used for reading */ Lock readLock(); /** * Returns the lock used for writing. * * @return the lock used for writing */ Lock writeLock();}

  ReentrantReadWriteLock實現了ReadWriteLock接口,如果調用readLock().lock()的話,被當前線程鎖住的資源,其他所有線程都可以進行讀,但是不能進行寫,也不允許其他線程進行writeLock().lock()來對當前資源進行加寫鎖;如果一個線程調用寫鎖writeLock().lock(),那么之后當前線程可以進行寫操作,其他線程不能同時寫。


  上面說到的公平性,如果是非公平的,就是JVM決定喚醒哪個等待線程獲得鎖,而公平的鎖,即喚醒當前在等待的線程中,等待時間最長的那個線程獲得鎖。默認情況下,ReentrantLockReentrantReadWriteLock都是非公平鎖,但是可以設置為公平鎖,相對于公平鎖,非公平鎖有更好的效率,因為公平的獲取鎖沒有考慮到操作系統對線程的調度因素,這樣造成JVM對于等待中的線程調度次序和操作系統對線程的調度之間的不匹配,而且對于鎖的快速且重復的獲取過程中,連續獲取的概率是非常高的,而公平鎖會壓制這種情況,雖然公平性得以保障,但是響應比卻下降了。

總結

  相比于synchronized的笨重,Lock更加靈活,如果獲取synchronized鎖的線程阻塞了,那么其他等待鎖的線程只能等待,十分影響程序效率,而Lock可以讓線程只等待一段時間或者中斷線程的等待,還可以加讀鎖,同時多個線程都可以進行讀,效率十分高。   但是Lock實現鎖需要程序員多操點心了,獲取synchronized鎖的線程執行完畢之后就會釋放鎖,不需要手動釋放,而且如果線程發生異常,JVM會讓線程自動釋放鎖,但是Lock鎖需要程序員手動釋放鎖,并且要處理異常。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲精品动漫久久久久| 欧美日本高清视频| 中文字幕免费国产精品| 91免费的视频在线播放| 日韩电影中文字幕一区| 国产精品专区一| 久久久国产精品免费| 久久精品国产91精品亚洲| 亚洲电影免费观看高清完整版在线观看| 欧美国产亚洲精品久久久8v| 亚洲欧美成人网| 欧美精品久久一区二区| 国产91对白在线播放| 性欧美视频videos6一9| 欧美视频在线观看 亚洲欧| 欧美中文字幕在线| 国产日韩欧美在线观看| 欧美日韩高清区| 国产在线观看精品一区二区三区| 成人国产精品一区二区| 欧美一级淫片丝袜脚交| 国产69精品久久久久99| 亚洲成avwww人| 久久久久久久999精品视频| 狠狠久久亚洲欧美专区| 成人黄色大片在线免费观看| 国产福利精品在线| 情事1991在线| 国产午夜精品视频免费不卡69堂| 国产精品一区二区三区久久| 91麻豆国产精品| 亚洲欧美一区二区三区在线| 一本色道久久88精品综合| 亚洲第一级黄色片| 欧美人交a欧美精品| 久久久久国色av免费观看性色| 最好看的2019的中文字幕视频| 日韩精品丝袜在线| 日日摸夜夜添一区| 91久久国产综合久久91精品网站| 久久免费高清视频| 日韩av一区二区在线观看| 亚洲精品久久7777777| 韩国国内大量揄拍精品视频| 久色乳综合思思在线视频| 欧美巨乳美女视频| 欧美在线免费看| 日韩精品高清在线| 日韩精品在线免费观看视频| 欧美激情视频一区二区| 欧美另类老女人| 555www成人网| 欧美精品videofree1080p| 日韩免费高清在线观看| 亚洲国产成人精品女人久久久| 久久精品久久久久| 中文欧美在线视频| 欧美成人午夜激情视频| 98午夜经典影视| 国产成人精品综合久久久| 精品福利免费观看| 成人中文字幕在线观看| 亚洲欧美另类国产| 国产91对白在线播放| 在线观看精品国产视频| 亚洲视频777| 久久精品视频亚洲| 最近日韩中文字幕中文| 欧洲午夜精品久久久| 久久精品男人天堂| 91午夜理伦私人影院| 成人黄色中文字幕| 国产综合久久久久| 国产一区二区久久精品| 亚洲在线免费看| 69国产精品成人在线播放| 国产97色在线| 亚洲女人天堂色在线7777| 国产成+人+综合+亚洲欧洲| 日韩免费在线电影| 亚洲激情在线视频| 成人国产精品久久久久久亚洲| 欧美一区二粉嫩精品国产一线天| 欧美成人国产va精品日本一级| 在线亚洲欧美视频| 国内精品美女av在线播放| 日韩av在线网页| 亚洲人成在线观看| 欧美极品美女视频网站在线观看免费| 亚洲天堂网站在线观看视频| 亚洲性猛交xxxxwww| 亚洲国产精品字幕| 日本精品久久电影| 最近2019年好看中文字幕视频| 日韩av片电影专区| 狠狠色狠狠色综合日日小说| 亚洲精品第一国产综合精品| 欧美整片在线观看| 欧美大尺度激情区在线播放| zzijzzij亚洲日本成熟少妇| 欧美视频在线免费| 久久精品亚洲一区| 日韩欧美在线一区| 亚洲第一天堂无码专区| 97视频在线观看播放| 成人激情视频在线观看| 日韩免费在线播放| 久久久久免费视频| 国产精品av免费在线观看| 欧美日韩国产色视频| 成人午夜一级二级三级| 欧美乱大交做爰xxxⅹ性3| 国产美女精彩久久| 精品成人69xx.xyz| 亚洲黄色av网站| 欧美成人在线免费| 欧美在线中文字幕| 68精品国产免费久久久久久婷婷| 精品一区二区三区四区在线| 久久综合色影院| 国产精品美女久久久久久免费| 久久久精品国产网站| 日韩精品亚洲元码| 久久久精品一区| 亚洲缚视频在线观看| 自拍偷拍亚洲一区| 91美女福利视频高清| 欧美日韩裸体免费视频| 国产香蕉一区二区三区在线视频| 久久av在线看| 免费av一区二区| 国产精品极品尤物在线观看| 日韩综合视频在线观看| 国产欧美va欧美va香蕉在| 亚洲xxx大片| 亚洲日本欧美中文幕| 亚洲综合社区网| 欧美老女人性生活| 国产精品久久久| 91国内产香蕉| 国内免费精品永久在线视频| 九九综合九九综合| 欧美一级大片在线免费观看| 亚洲国产另类 国产精品国产免费| 欧美大全免费观看电视剧大泉洋| 国产亚洲欧洲在线| 97在线免费观看| 亚洲aⅴ男人的天堂在线观看| 国产91精品久| 国产日韩视频在线观看| 精品毛片三在线观看| 亚洲大胆美女视频| 91国在线精品国内播放| 91国偷自产一区二区三区的观看方式| 欧美激情一区二区三级高清视频| 日韩精品视频在线观看网址| 国产精品美女在线| 色香阁99久久精品久久久| 免费91在线视频| 国产精品视频资源| 国产不卡一区二区在线播放| 国产精品羞羞答答| 亚洲xxx大片| 欧美日韩免费在线|