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

首頁 > 開發 > Java > 正文

Java多線程之顯示鎖和內置鎖總結詳解

2024-07-13 10:13:57
字體:
來源:轉載
供稿:網友

總結javascript/25483.html">java/237262.html">多線程之顯示鎖和內置鎖

Java中具有通過Synchronized實現的內置鎖,和ReentrantLock實現的顯示鎖,這兩種鎖各有各的好處,算是互有補充,這篇文章就是做一個總結。

*Synchronized*

內置鎖獲得鎖和釋放鎖是隱式的,進入synchronized修飾的代碼就獲得鎖,走出相應的代碼就釋放鎖。

synchronized(list){ //獲得鎖  list.append();  list.count();}//釋放鎖

通信

與Synchronized配套使用的通信方法通常有wait(),notify()。

wait()方法會立即釋放當前鎖,并進入等待狀態,等待到相應的notify并重新獲得鎖過后才能繼續執行;notify()不會立刻立刻釋放鎖,必須要等notify()所在線程執行完synchronized塊中的所有代碼才會釋放。用如下代碼來進行驗證:

public static void main(String[] args){	List list = new LinkedList();	Thread r = new Thread(new ReadList(list));	Thread w = new Thread(new WriteList(list));	r.start();	w.start();}class ReadList implements Runnable{	private List list;	public ReadList(List list){		this.list = list;	}	@Override	  public void run(){		System.out.println("ReadList begin at "+System.currentTimeMillis());		synchronized (list){			try {				Thread.sleep(1000);				System.out.println("list.wait() begin at "+System.currentTimeMillis());				list.wait();				System.out.println("list.wait() end at "+System.currentTimeMillis());			}			catch (InterruptedException e) {				e.printStackTrace();			}		}		System.out.println("ReadList end at "+System.currentTimeMillis());	}}class WriteList implements Runnable{	private List list;	public WriteList(List list){		this.list = list;	}	@Override	  public void run(){		System.out.println("WriteList begin at "+System.currentTimeMillis());		synchronized (list){			System.out.println("get lock at "+System.currentTimeMillis());			list.notify();			System.out.println("list.notify() at "+System.currentTimeMillis());			try {				Thread.sleep(2000);			}			catch (InterruptedException e) {				e.printStackTrace();			}			System.out.println("get out of block at "+System.currentTimeMillis());		}		System.out.println("WriteList end at "+System.currentTimeMillis());	}}

運行結果:

ReadList begin at 1493650526582WriteList begin at 1493650526582list.wait() begin at 1493650527584get lock at 1493650527584list.notify() at 1493650527584get out of block at 1493650529584WriteList end at 1493650529584list.wait() end at 1493650529584ReadList end at 1493650529584

可見讀線程開始運行,開始wait過后,寫線程才獲得鎖;寫線程走出同步塊而不是notify過后,讀線程才wait結束,亦即獲得鎖。所以notify不會釋放鎖,wait會釋放鎖。值得一提的是,notifyall()會通知等待隊列中的所有線程。

編碼

編碼模式比較簡單,單一,不必顯示的獲得鎖,釋放鎖,能降低因粗心忘記釋放鎖的錯誤。使用模式如下:

synchronized(object){  }

靈活性

1.內置鎖在進入同步塊時,采取的是無限等待的策略,一旦開始等待,就既不能中斷也不能取消,容易產生饑餓與死鎖的問題
2.在線程調用notify方法時,會隨機選擇相應對象的等待隊列的一個線程將其喚醒,而不是按照FIFO的方式,如果有強烈的公平性要求,比如FIFO就無法滿足

性能

Synchronized在JDK1.5及之前性能(主要指吞吐率)比較差,擴展性也不如ReentrantLock。但是JDK1.6以后,修改了管理內置鎖的算法,使得Synchronized和標準的ReentrantLock性能差別不大。

*ReentrantLock*

ReentrantLock是顯示鎖,需要顯示進行 lock 以及 unlock 操作。

通信

與ReentrantLock搭配的通行方式是Condition,如下:

private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); condition.await();//this.wait(); condition.signal();//this.notify(); condition.signalAll();//this.notifyAll();

Condition是被綁定到Lock上的,必須使用lock.newCondition()才能創建一個Condition。從上面的代碼可以看出,Synchronized能實現的通信方式,Condition都可以實現,功能類似的代碼寫在同一行中。而Condition的優秀之處在于它可以為多個線程間建立不同的Condition,比如對象的讀/寫Condition,隊列的空/滿Condition,在JDK源碼中的ArrayBlockingQueue中就使用了這個特性:

public ArrayBlockingQueue(int capacity, boolean fair) {  if (capacity <= 0)    throw new IllegalArgumentException();  this.items = new Object[capacity];  lock = new ReentrantLock(fair);  notEmpty = lock.newCondition();  notFull = lock.newCondition();}public void put(E e) throws InterruptedException {  checkNotNull(e);  final ReentrantLock lock = this.lock;  lock.lockInterruptibly();  try {    while (count == items.length)      notFull.await();    enqueue(e);  } finally {    lock.unlock();  }}public E take() throws InterruptedException {  final ReentrantLock lock = this.lock;  lock.lockInterruptibly();  try {    while (count == 0)      notEmpty.await();    return dequeue();  } finally {    lock.unlock();  }}private void enqueue(E x) {  // assert lock.getHoldCount() == 1;  // assert items[putIndex] == null;  final Object[] items = this.items;  items[putIndex] = x;  if (++putIndex == items.length)    putIndex = 0;  count++;  notEmpty.signal();}private E dequeue() {  // assert lock.getHoldCount() == 1;  // assert items[takeIndex] != null;  final Object[] items = this.items;  @SuppressWarnings("unchecked")  E x = (E) items[takeIndex];  items[takeIndex] = null;  if (++takeIndex == items.length)    takeIndex = 0;  count--;  if (itrs != null)    itrs.elementDequeued();  notFull.signal();  return x;}

編碼

Lock lock = new ReentrantLock();lock.lock();try{ }finally{  lock.unlock();}

相比于Synchronized要復雜一些,而且一定要記得在finally中釋放鎖而不是其他地方,這樣才能保證即使出了異常也能釋放鎖。

靈活性

1.lock.lockInterruptibly()可以使得線程在等待鎖是支持響應中斷;lock.tryLock()可以使得線程在等待一段時間過后如果還未獲得鎖就停止等待而非一直等待。有了這兩種機制就可以更好的制定獲得鎖的重試機制,而非盲目一直等待,可以更好的避免饑餓和死鎖問題

2.ReentrantLock可以成為公平鎖(非默認的),所謂公平鎖就是鎖的等待隊列的FIFO,不過公平鎖會帶來性能消耗,如果不是必須的不建議使用。這和CPU對指令進行重排序的理由是相似的,如果強行的按照代碼的書寫順序來執行指令,就會浪費許多時鐘周期,達不到最大利用率

性能

雖然Synchronized和標準的ReentrantLock性能差別不大,但是ReentrantLock還提供了一種非互斥的讀寫鎖,

也就是不強制每次最多只有一個線程能持有鎖,它會避免“讀/寫”沖突,“寫/寫”沖突,但是不會排除“讀/讀”沖突,

因為“讀/讀”并不影響數據的完整性,所以可以多個讀線程同時持有鎖,這樣在讀寫比較高的情況下,性能會有很大的提升。

下面用兩種鎖分別實現的線程安全的linkedlist:

class RWLockList {	//讀寫鎖	private List list;	private final ReadWriteLock lock = new ReentrantReadWriteLock();	private final Lock readLock = lock.readLock();	private final Lock writeLock = lock.writeLock();	public RWLockList(List list){		this.list = list;	}	public int get(int k) {		readLock.lock();		try {			return (int)list.get(k);		}		finally {			readLock.unlock();		}	}	public void put(int value) {		writeLock.lock();		try {			list.add(value);		}		finally {			writeLock.unlock();		}	}}class SyncList {	private List list;	public SyncList(List list){		this.list = list;	}	public synchronized int get(int k){		return (int)list.get(k);	}	public synchronized void put(int value){		list.add(value);	}}

讀寫鎖測試代碼:

List list = new LinkedList();for (int i=0;i<10000;i++){	list.add(i);}RWLockList rwLockList = new RWLockList(list);//初始化數據Thread writer = new Thread(new Runnable() {	@Override	  public void run() {		for (int i=0;i<10000;i++){			rwLockList.put(i);		}	}});Thread reader1 = new Thread(new Runnable() {	@Override	  public void run() {		for (int i=0;i<10000;i++){			rwLockList.get(i);		}	}});Thread reader2 = new Thread(new Runnable() {	@Override	  public void run() {		for (int i=0;i<10000;i++){			rwLockList.get(i);		}	}});long begin = System.currentTimeMillis();writer.start();reader1.start();reader2.start();try {	writer.join();	reader1.join();	reader2.join();}catch (InterruptedException e) {	e.printStackTrace();}System.out.println("RWLockList take "+(System.currentTimeMillis()-begin) + "ms");

同步鎖測試代碼:

List list = new LinkedList();for (int i=0;i<10000;i++){  list.add(i);}SyncList syncList = new SyncList(list);//初始化數據Thread writerS = new Thread(new Runnable() {  @Override  public void run() {    for (int i=0;i<10000;i++){      syncList.put(i);    }  }});Thread reader1S = new Thread(new Runnable() {  @Override  public void run() {    for (int i=0;i<10000;i++){      syncList.get(i);    }  }});Thread reader2S = new Thread(new Runnable() {  @Override  public void run() {    for (int i=0;i<10000;i++){      syncList.get(i);    }  }});long begin1 = System.currentTimeMillis();writerS.start();reader1S.start();reader2S.start();try {  writerS.join();  reader1S.join();  reader2S.join();} catch (InterruptedException e) {  e.printStackTrace();}System.out.println("SyncList take "+(System.currentTimeMillis()-begin1) + "ms");

結果:

RWLockList take 248msRWLockList take 255msRWLockList take 249msRWLockList take 224ms SyncList take 351msSyncList take 367msSyncList take 315msSyncList take 323ms

可見讀寫鎖的確是優于純碎的互斥鎖

總結

內置鎖最大優點是簡潔易用,顯示鎖最大優點是功能豐富,所以能用內置鎖就用內置鎖,在內置鎖功能不能滿足之時在考慮顯示鎖。

以上就是本文關于Java多線程之顯示鎖和內置鎖總結詳解的全部內容,希望對大家有所幫助。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
www.日韩.com| 欧美色视频日本高清在线观看| 伊人亚洲福利一区二区三区| 欧美日韩免费观看中文| 国产成人精品视频在线| 2019中文字幕全在线观看| 免费99精品国产自在在线| www.99久久热国产日韩欧美.com| 日韩免费观看视频| 777午夜精品福利在线观看| 午夜美女久久久久爽久久| 欧美精品videos性欧美| 丁香五六月婷婷久久激情| 欧美一级在线播放| 亚洲va久久久噜噜噜| 精品久久久久久久久久久久| 国产精品电影一区| 亚洲男人天堂手机在线| 日韩欧美在线国产| 日韩美女视频中文字幕| 九色成人免费视频| 欧美刺激性大交免费视频| 国产91精品网站| 97碰碰碰免费色视频| 91精品视频在线| 国产精品免费小视频| 亚洲白拍色综合图区| 91网在线免费观看| 日韩在线观看免费全| 欧洲午夜精品久久久| 欧美日韩国产一区在线| 91精品久久久久久久久青青| 国产精品欧美在线| 亚洲色无码播放| 久久精品福利视频| 欧美一区二区色| 欧美激情第三页| 日韩欧美成人免费视频| 亚洲美女av电影| 亚洲精品福利免费在线观看| 性欧美在线看片a免费观看| 亚洲精品午夜精品| 亚洲网站视频福利| 亚洲第一在线视频| 久久久精品在线| 亚洲自拍偷拍在线| 久久精品国产2020观看福利| 日韩成人小视频| 91视频-88av| 国语自产精品视频在免费| 亚洲成人精品久久久| 92国产精品久久久久首页| 久久不射热爱视频精品| 国产精品三级美女白浆呻吟| 亚洲国产美女久久久久| 亚洲一区二区在线播放| 欧美成人精品不卡视频在线观看| 成人黄色在线免费| 91精品国产免费久久久久久| 亚洲国产日韩精品在线| 亚洲欧美三级伦理| 亚洲欧美国产日韩中文字幕| 日韩女优人人人人射在线视频| 亚洲一区二区三区成人在线视频精品| 中文字幕成人精品久久不卡| 中文字幕综合在线| 久久久久久久久久久91| 亚洲图片欧美午夜| 亚洲欧洲视频在线| 亚洲精品不卡在线| 欧美日韩免费观看中文| 日韩av综合网| 久久精品视频免费播放| 日韩av理论片| 国产精品丝袜一区二区三区| 97视频国产在线| 午夜精品一区二区三区在线| 欧美激情亚洲综合一区| 伊人久久综合97精品| 中文字幕不卡av| 亚洲自拍小视频免费观看| 亚洲精品日韩丝袜精品| 欧美亚洲国产另类| 欧美一乱一性一交一视频| 久久精品中文字幕免费mv| 国产精品草莓在线免费观看| 国产精品一区二区三区在线播放| 高跟丝袜一区二区三区| 亚洲区在线播放| 中文字幕精品在线| 亚洲第一国产精品| 亚洲精品美女在线观看播放| www.xxxx精品| 国产美女扒开尿口久久久| 欧美性生交xxxxx久久久| 亚洲电影天堂av| 亚洲欧美视频在线| 亚洲日韩第一页| 国产亚洲精品久久久久久牛牛| 国产精品视频99| 欧美性猛xxx| 国内精品久久久久久久| 日韩成人在线电影网| 精品久久久视频| 亚洲精品国产拍免费91在线| 成人h视频在线观看播放| 福利一区福利二区微拍刺激| 性色av香蕉一区二区| 国产婷婷成人久久av免费高清| 国产偷亚洲偷欧美偷精品| 午夜精品三级视频福利| 国产精品免费视频xxxx| 日韩欧美在线第一页| 亚洲日韩欧美视频一区| 欧美精品在线免费播放| 中文综合在线观看| 国产成人久久精品| 国产精品久久久久不卡| 欧美午夜电影在线| 亚洲精品久久视频| 亚洲成人久久一区| 日韩欧美在线国产| 成人黄色大片在线免费观看| 欧美日韩亚洲成人| 国产欧美一区二区白浆黑人| 欧美裸体视频网站| 992tv成人免费影院| 91国自产精品中文字幕亚洲| 国产精品网红直播| 色yeye香蕉凹凸一区二区av| 亚洲男人第一av网站| 亚洲精品视频在线观看视频| 亚洲综合中文字幕68页| 性欧美激情精品| 精品国产一区二区三区久久狼黑人| 国产精品国产三级国产aⅴ9色| 欧美精品在线观看91| 国产精品91久久久久久| 久久天天躁狠狠躁夜夜躁2014| 欧美精品福利视频| 成人黄色免费片| 综合136福利视频在线| 成人情趣片在线观看免费| 亚洲国内精品视频| 日韩在线免费av| 91国产一区在线| 国产精品吊钟奶在线| 欧美性色19p| 国产精品人成电影| 91嫩草在线视频| 亚洲精品v欧美精品v日韩精品| 成人精品一区二区三区电影黑人| 中文字幕在线看视频国产欧美在线看完整| 日本高清久久天堂| 亚洲精品国产综合久久| 亚洲最大在线视频| 亚洲成人精品视频| 久久综合免费视频影院| 欧美亚洲免费电影| 亚洲精品理论电影| www.美女亚洲精品| 欧美专区国产专区| 疯狂欧美牲乱大交777| 亚洲天堂网在线观看|