多執行緒與併發-----Lock鎖技術

pengzhisen123發表於2018-05-12

Lock

    java.util.concurrent.locks 為鎖和等待條件提供一個框架的介面和類,

    

介面摘要

Condition

Condition Object 監視器方法(waitnotify 和 notifyAll)分解成截然不同的物件,以便通過將這些物件與任意 Lock 實現組合使用,為每個物件提供多個等待 setwait-set)。

Lock

Lock 實現提供了比使用 synchronized 方法和語句可獲得的更廣泛的鎖定操作。

ReadWriteLock

ReadWriteLock 維護了一對相關的,一個用於只讀操作,另一個用於寫入操作。

類摘要

AbstractOwnableSynchronizer

可以由執行緒以獨佔方式擁有的同步器。

AbstractQueuedLongSynchronizer

long 形式維護同步狀態的一個 AbstractQueuedSynchronizer 版本。

AbstractQueuedSynchronizer

為實現依賴於先進先出 (FIFO) 等待佇列的阻塞鎖和相關同步器(訊號量、事件,等等)提供一個框架。

LockSupport

用來建立鎖和其他同步類的基本執行緒阻塞原語。

ReentrantLock

一個可重入的互斥鎖 Lock,它具有與使用 synchronized 方法和語句所訪問的隱式監視器鎖相同的一些基本行為和語義,但功能更強大。

ReentrantReadWriteLock

支援與 ReentrantLock 類似語義的 ReadWriteLock 實現。

ReentrantReadWriteLock.ReadLock

ReentrantReadWriteLock.readLock() 方法返回的鎖。

ReentrantReadWriteLock.WriteLock

ReentrantReadWriteLock.writeLock() 方法返回的鎖。

Lock比傳統執行緒模型中的synchronized更加物件導向,鎖本身也是一個物件,兩個執行緒執行的程式碼要實現同步互斥效果,就要使用同一個鎖物件。鎖要上在要操作的資源類的內部方法中,而不是執行緒程式碼中。

public interface Lock

所有已知實現類:

ReentrantLock, ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock 

隨著靈活性的增加,也帶來了更多的責任。不使用塊結構鎖就失去了使用 synchronized 方法和語句時會出現的鎖自動釋放功能。在大多數情況下,應該使用以下語句:

 Lock l = ...;

     l.lock();

     try {

         // access the resource protected by this lock

     } finally {

         l.unlock();

     }

鎖定和取消鎖定出現在不同作用範圍中時,必須謹慎地確保保持鎖定時所執行的所有程式碼用 try-finally try-catch 加以保護,以確保在必要時釋放鎖。

方法摘要

 void

lock()           獲取鎖。

 void

lockInterruptibly()           如果當前執行緒未被中斷,則獲取鎖。

 Condition

newCondition()           返回繫結到此 Lock 例項的新 Condition 例項。

 boolean

tryLock()           僅在呼叫時鎖為空閒狀態才獲取該鎖。

 boolean

tryLock(long time, TimeUnit unit)           如果鎖在給定的等待時間內空閒,並且當前執行緒未被中斷,則獲取鎖。

 void

unlock()           釋放鎖。

Locksynchronized對比,列印字串例子


具體程式碼如下:


import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadLock {

	public static void main(String[] args) {
		
		new ThreadLock().init();
	}
	
	public void init(){
		/*在靜態方法中不能new內部類的例項物件,
		因為內部類的最重要的一個特點就是它可以直接訪問它外部類的成員變數。成員變數是物件身上的。物件建立完成了,才會為成員變數分配空間。能呼叫成員變數,意味著一定有了例項物件.
		main方法是靜態的,它執行的時候可以不用建立那個物件。這就矛盾了。 
		 */
		final Outputer outputer=new Outputer();//建立內部類
		new Thread(new Runnable() {//建立一個執行緒
			public void run() {
				while(true){
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					outputer.output("lisi");
				}
				
			}
		}).start();
		
		new Thread(new Runnable() {//建立一個執行緒
			public void run() {
				while(true){
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					outputer.output("zhangsan");
				}
				
			}
		}).start();
	}
		
	//內部類
	class Outputer{
		Lock lock =new ReentrantLock();
		public void output(String name){
			int len=name.length();
			lock.lock();
			try{
				for(int i=0;i<len;i++){
					System.out.print(name.charAt(i));
				}
				System.out.println();
			}finally{
				lock.unlock();
			}			
		}
	}
}

相關文章