1. 程式人生 > >Java多執行緒學習筆記18之Lock的使用

Java多執行緒學習筆記18之Lock的使用

詳細程式碼見:github程式碼地址

 

本節內容:

    公平鎖和非公平鎖以及ReentrantLock常用方法的使用

1) 公平鎖和非公平鎖

2) getHoldCount()、getQueueLength()、getWaitQueueLength()

3) hasQueueThread()、hasQueueThreads()、hasWaiters()

4) lockInterruptibly()、tryLock()、tryLock(long timeout, TimeUnit unit)

 

3.公平鎖和非公平鎖以及常用方法的使用

(1) 公平鎖和非公平鎖
公平鎖和非公平鎖:

    鎖Lock分為"公平鎖"和"非公平鎖",公平鎖表示執行緒獲取鎖的順序是按照執行緒

加鎖的順序來分配的,即先來先得的FIFO先進先出順序。而非公平鎖就是一種

獲得鎖的搶佔機制,是隨機獲得鎖的,和公平鎖不一樣的就是先來的不一定先得

到鎖,這個方式可能造成某些執行緒一直拿不到鎖,結果也就是不公平了。

預設情況下ReentrantLock的建構函式不傳遞引數是非公平鎖false,如果傳遞引數則指定是否公平。
對於這兩種鎖的支援,ReentrantLock實際上是內建了兩個鎖來分分別實現這兩種鎖,一個叫FairSync
(公平鎖),一個叫NonFairSync(非公平鎖).由於這是多執行緒知識,我後面會開一個高併發專欄,講講
原始碼及一些框架的用法。


舉例:

package chapter04.section01.thread_4_1_9.project_1_Fair_noFair_test;

import java.util.concurrent.locks.ReentrantLock;

public class Service {
	
	private ReentrantLock lock;
	
	public Service(boolean isFair) {
		super();
		lock = new ReentrantLock(isFair);
	}
	
	public void serviceMethod() {
		try {
			lock.lock();
			System.out.println("ThreadName=" + Thread.currentThread().getName()
					+ "獲得鎖定");
		} finally {
			// TODO: handle finally clause
			lock.unlock();
		}
	}
}


package chapter04.section01.thread_4_1_9.project_1_Fair_noFair_test;

public class RunFair {

	public static void main(String[] args) throws InterruptedException {
		final Service service = new Service(true);

		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				System.out.println("★執行緒" + Thread.currentThread().getName()
						+ "運行了");
				service.serviceMethod();
			}
		};

		Thread[] threadArray = new Thread[10];
		for (int i = 0; i < 10; i++) {
			threadArray[i] = new Thread(runnable);
		}
		for (int i = 0; i < 10; i++) {
			threadArray[i].start();
		}
	}
}
/*
result:
★執行緒Thread-1運行了
★執行緒Thread-8運行了
★執行緒Thread-6運行了
★執行緒Thread-7運行了
★執行緒Thread-3運行了
★執行緒Thread-5運行了
★執行緒Thread-0運行了
★執行緒Thread-4運行了
★執行緒Thread-2運行了
★執行緒Thread-9運行了
ThreadName=Thread-0獲得鎖定
ThreadName=Thread-4獲得鎖定
ThreadName=Thread-6獲得鎖定
ThreadName=Thread-8獲得鎖定
ThreadName=Thread-2獲得鎖定
ThreadName=Thread-1獲得鎖定
ThreadName=Thread-5獲得鎖定
ThreadName=Thread-3獲得鎖定
ThreadName=Thread-7獲得鎖定
ThreadName=Thread-9獲得鎖定
*/

可以看到大體上是這個順序,有興趣可以去讀讀原始碼

package chapter04.section01.thread_4_1_9.project_1_Fair_noFair_test;

public class RunNotFair {
	public static void main(String[] args) {
		final Service service = new Service(false);
		
		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				System.out.println("★執行緒" + Thread.currentThread().getName()
						+ "運行了");
				service.serviceMethod();
			}
		};
		
		Thread[] threadArray = new Thread[10];
		for(int i = 0; i < 10; i++) {
			threadArray[i] = new Thread(runnable);
		}
		
		for(int i = 0; i < 10; i++) {
			threadArray[i].start();
		}
	}
}
/*
result:
★執行緒Thread-1運行了
★執行緒Thread-6運行了
★執行緒Thread-4運行了
★執行緒Thread-2運行了
★執行緒Thread-0運行了
★執行緒Thread-5運行了
★執行緒Thread-3運行了
★執行緒Thread-7運行了
★執行緒Thread-9運行了
ThreadName=Thread-9獲得鎖定
ThreadName=Thread-7獲得鎖定
ThreadName=Thread-3獲得鎖定
ThreadName=Thread-1獲得鎖定
ThreadName=Thread-0獲得鎖定
ThreadName=Thread-2獲得鎖定
ThreadName=Thread-5獲得鎖定
ThreadName=Thread-6獲得鎖定
ThreadName=Thread-4獲得鎖定
★執行緒Thread-8運行了
ThreadName=Thread-8獲得鎖定
*/

可以看到非公平鎖THread-1先執行了竟然是第一個獲得鎖。


4. ReentrantLock例項的方法的使用

(1) 方法getHoldCount(), getQueueLength()和getWaitQueueLength()的測試

1) getHoldCount()
int getHoldCount()的作用是查詢當前執行緒保持此鎖定的個數,也就是呼叫lock()方法的次數
文件:

public int getHoldCount​()
Queries the number of holds on this lock by the current thread.
A thread has a hold on a lock for each lock action that is not matched by an unlock 
action.
查詢當前執行緒對該鎖的持有數量
對於每個鎖操作,執行緒都持有一個鎖,而鎖操作與解鎖操作不匹配

The hold count information is typically only used for testing and debugging purposes. 
For example, if a certain section of code should not be entered with the lock already 
held then we can assert that fact:
擁有鎖的資訊通常只用於測試和除錯目的
例如,如果不應該進入已經持有鎖的程式碼段,我們可以斷言:
(在實現中,assertion就是在程式中的一條語句,它對一個boolean表示式進行檢查,一個正確程式必須保證這個
boolean表示式的值為true;如果該值為false,說明程式已經處於不正確的狀態下,系統將給出警告並退出。)
 class X {
   ReentrantLock lock = new ReentrantLock();
   // ...
   public void m() {
     assert lock.getHoldCount() == 0;
     lock.lock();
     try {
       // ... method body
     } finally {
       lock.unlock();
     }
   }
 }
Returns:
the number of holds on this lock by the current thread, or zero if this lock is not held
by the current thread
返回:
當前執行緒持有此鎖的次數,如果當前執行緒未持有此鎖,則為0

 

舉個例子:

package chapter04.section01.thread_4_1_10.project_1_lockMethodTest1.test1;

import java.util.concurrent.locks.ReentrantLock;

public class Service {
	
	private ReentrantLock lock = new ReentrantLock();
	
	public void serviceMethod1() {
		try {
			lock.lock();
			System.out.println("serviceMethod1 getHoldCount="
					+ lock.getHoldCount());
			serviceMethod2();
		} finally {
			// TODO: handle finally clause
		}
	}
	
	public void serviceMethod2() {
		try {
			lock.lock();
			System.out.println("serviceMethod2 getHoldCount="
					+ lock.getHoldCount());
		} finally {
			// TODO: handle finally clause
		}
	}
}


package chapter04.section01.thread_4_1_10.project_1_lockMethodTest1.test1;

public class Run {
	public static void main(String[] args) {
		Service service = new Service();
		service.serviceMethod1();
	}
}
/*
result:
serviceMethod1 getHoldCount=1
serviceMethod2 getHoldCount=2
*/


2) getQueueLength()

方法int getQueueLength()的作用是返回正在等待獲取此鎖定的執行緒估計數
文件:

public final int getQueueLength​()
Returns an estimate of the number of threads waiting to acquire. The value is only an 
estimate because the number of threads may change dynamically while this method traverses 
internal data structures. This method is designed for use in monitoring system state, 
not for synchronization control.
Returns:
the estimated number of threads waiting for this lock
返回正在等待獲取鎖的執行緒數量的估計值。這個值只是一個估計值,因為這個方法遍歷內部資料結構時,執行緒的
數量可能會動態變化。本方法是設計用於監測系統狀態,不是用於同步控制
返回:
等待這個鎖的執行緒的估計數量

舉例:

package chapter04.section01.thread_4_1_10.project_1_lockMethodTest1.test2;

import java.util.concurrent.locks.ReentrantLock;

public class Service {

	public ReentrantLock lock = new ReentrantLock();

	public void serviceMethod() {
		try {
			lock.lock();
			System.out.println("ThreadName=" + Thread.currentThread().getName()
					+ "進入方法!");
			Thread.sleep(Integer.MAX_VALUE);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
}


package chapter04.section01.thread_4_1_10.project_1_lockMethodTest1.test2;

public class Run {
	public static void main(String[] args) throws InterruptedException {
		final Service service = new Service();
		
		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				service.serviceMethod();
			}
		};
		
		Thread[] threadArray = new Thread[10];
		for(int i = 0; i < 10; i++) {
			threadArray[i] = new Thread(runnable);
		}
		for(int i = 0; i < 10; i++) {
			threadArray[i].start();
		}
		Thread.sleep(2000);
		System.out.println("有執行緒數: " + service.lock.getQueueLength() + "在等待獲取鎖!");
	}
}
/*
result:
ThreadName=Thread-3進入方法!
有執行緒數: 9在等待獲取鎖!
*/

 

3) getWaitQueueLength(Condition condition)
方法int getWaitQueueLength(Condition condition)的作用是返回等待與此鎖定相關的
給定條件Condition的執行緒估計數,比如有5個執行緒,每個執行緒都執行了同一個condition物件
await()方法,則呼叫getWaitQueueLength(Condition condition)方法時返回的int值是5

文件:

public int getWaitQueueLength​(Condition condition)
Returns an estimate of the number of threads waiting on the given condition 
associated with this lock. Note that because timeouts and interrupts may occur 
at any time, the estimate serves only as an upper bound on the actual number of 
waiters. This method is designed for use in monitoring of the system state, not 
for synchronization control.
Parameters:
condition - the condition
Returns:
the estimated number of waiting threads
Throws:
IllegalMonitorStateException - if this lock is not held 如果不持有此鎖
IllegalArgumentException - if the given condition is not associated with this lock
							如果給定條件與此鎖無關
NullPointerException - if the condition is null
						如果條件為null
返回等待於此鎖關聯的給定條件的執行緒數的估計值。由於超時和中斷可能在任何時候發生,因此此估計
僅作為實際等待者數量的上限。該方法用於系統狀態的監控,而不是同步控制
引數:
condition - 條件
返回:
等待執行緒的估計數量

 

舉個例子:

package chapter04.section01.thread_4_1_10.project_1_lockMethodTest1.test3;

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

public class Service {

	private ReentrantLock lock = new ReentrantLock();
	private Condition newCondition = lock.newCondition();

	public void waitMethod() {
		try {
			lock.lock();
			newCondition.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}

	public void notityMethod() {
		try {
			lock.lock();
			System.out.println("有" + lock.getWaitQueueLength(newCondition)
					+ "個執行緒正在等待newCondition");
			newCondition.signal();
		} finally {
			lock.unlock();
		}
	}
}


package chapter04.section01.thread_4_1_10.project_1_lockMethodTest1.test3;

public class Run {

	public static void main(String[] args) throws InterruptedException {
		final Service service = new Service();

		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				service.waitMethod();
			}
		};

		Thread[] threadArray = new Thread[10];
		for (int i = 0; i < 10; i++) {
			threadArray[i] = new Thread(runnable);
		}
		for (int i = 0; i < 10; i++) {
			threadArray[i].start();
		}
		Thread.sleep(2000);
		service.notityMethod();
	}
}
/*
result:
有10個執行緒正在等待newCondition
*/

 

(2) 方法hasQueueThread()、hasQueueThreads()和hasWaiters()的測試

1) hasQueueThread()和hasQueueThreads()
方法boolean hasQueueThread(Thread thread)的作用是查詢指定的執行緒是否正在等待獲取
此鎖定
方法boolean hasQueueThreads()的作用是查詢是否有執行緒正在等待獲取此鎖定

舉個例子:

package chapter04.section01.thread_4_1_11.project_1_lockMethodTest2.test1;

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

public class Service {

	public ReentrantLock lock = new ReentrantLock();
	public Condition newCondition = lock.newCondition();
	
	public void waitMethod() {
		try {
			lock.lock();
			Thread.sleep(Integer.MAX_VALUE);
		} catch (InterruptedException e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}	
}


package chapter04.section01.thread_4_1_11.project_1_lockMethodTest2.test1;

public class Run {
	public static void main(String[] args) throws InterruptedException {
		final Service service = new Service();

		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				service.waitMethod();
			}
		};

		Thread threadA = new Thread(runnable);
		threadA.start();

		Thread.sleep(500);

		Thread threadB = new Thread(runnable);
		threadB.start();

		Thread.sleep(500);
		System.out.println(service.lock.hasQueuedThread(threadA));
		System.out.println(service.lock.hasQueuedThread(threadB));
		System.out.println(service.lock.hasQueuedThreads());
	}
}
/*
result:
false
true
true
*/

 

2) hasWaiters(Condition condition)
方法boolean hasWaiters(Condition condition)的作用是查詢是否有執行緒正在等待與
此鎖定有關的condition條件。

文件:

public boolean hasWaiters​(Condition condition)
Queries whether any threads are waiting on the given condition associated with 
this lock. Note that because timeouts and interrupts may occur at any time, a 
true return does not guarantee that a future signal will awaken any threads. 
This method is designed primarily for use in monitoring of the system state.
查詢是否有任何執行緒正在等待與之關聯的給定條件的鎖。注意,由於超時和中斷可能在任何時候發生,
因此真正的返回並不保證將來的訊號會喚醒任何執行緒。該方法主要用於系統狀態監測。
Parameters:
condition - the condition
Returns:
true if there are any waiting threads
Throws:
IllegalMonitorStateException - if this lock is not held
IllegalArgumentException - if the given condition is not associated with this lock
NullPointerException - if the condition is null

 

舉個例子:

package chapter04.section01.thread_4_1_11.project_1_lockMethodTest2.test2;

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

public class Service {

	private ReentrantLock lock = new ReentrantLock();
	private Condition newCondition = lock.newCondition();

	public void waitMethod() {
		try {
			lock.lock();
			newCondition.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}

	public void notityMethod() {
		try {
			lock.lock();
			System.out.println("有沒有執行緒正在等待newCondition?"
					+ lock.hasWaiters(newCondition) + " 執行緒數是多少?"
					+ lock.getWaitQueueLength(newCondition));
			newCondition.signal();
		} finally {
			lock.unlock();
		}
	}
}


package chapter04.section01.thread_4_1_11.project_1_lockMethodTest2.test2;

public class Run {

	public static void main(String[] args) throws InterruptedException {
		final Service service = new Service();

		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				service.waitMethod();
			}
		};

		Thread[] threadArray = new Thread[10];
		for (int i = 0; i < 10; i++) {
			threadArray[i] = new Thread(runnable);
		}
		for (int i = 0; i < 10; i++) {
			threadArray[i].start();
		}
		Thread.sleep(2000);
		service.notityMethod();
	}
}
/*
有沒有執行緒正在等待newCondition?true 執行緒數是多少?10
*/

 

3) 方法isFair()、isHeldByCurrentThread()和isLocked()的測試

1) isFair()
方法boolean isFair()的作用是判斷是不是公平鎖

文件:

public boolean isFair​()
Returns true if this semaphore has fairness set true.
Returns:
true if this semaphore has fairness set true

 

舉例:

package chapter04.section01.thread_4_1_12.project_1_lockMethodTest3.test1;

import java.util.concurrent.locks.ReentrantLock;

public class Service {

	private ReentrantLock lock;

	public Service(boolean isFair) {
		super();
		lock = new ReentrantLock(isFair);
	}

	public void serviceMethod() {
		try {
			lock.lock();
			System.out.println("公平鎖情況:" + lock.isFair());
		} finally {
			lock.unlock();
		}
	}
}


package chapter04.section01.thread_4_1_12.project_1_lockMethodTest3.test1;

public class Run {

	public static void main(String[] args) throws InterruptedException {
		final Service service1 = new Service(true);
		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				service1.serviceMethod();
			}
		};
		Thread thread = new Thread(runnable);
		thread.start();

		final Service service2 = new Service(false);
		runnable = new Runnable() {
			@Override
			public void run() {
				service2.serviceMethod();
			}
		};
		thread = new Thread(runnable);
		thread.start();
	}
}
/*
result:
公平鎖情況:true
公平鎖情況:false
*/

 

2) isHeldByCurrentThread()
方法boolean isHeldByCurrentThread()的作用是查詢當前執行緒是否保持此鎖定

文件:

public boolean isHeldByCurrentThread​()
Queries if this lock is held by the current thread.
Analogous to the Thread.holdsLock(Object) method for built-in monitor locks, this 
method is typically used for debugging and testing. For example, a method that should 
only be called while a lock is held can assert that this is the case:
查詢當前執行緒是否持有此鎖
類似內建監視器鎖Thread.holdsLock(Object)方法。

 
 class X {
   ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() {
       assert lock.isHeldByCurrentThread();
       // ... method body
   }
 }
It can also be used to ensure that a reentrant lock is used in a non-reentrant manner, 
for example:

 
 class X {
   ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() {
       assert !lock.isHeldByCurrentThread();
       lock.lock();
       try {
           // ... method body
       } finally {
           lock.unlock();
       }
   }
 }
Returns:
true if current thread holds this lock and false otherwise

 

舉例:

package chapter04.section01.thread_4_1_12.project_1_lockMethodTest3.test2;

import java.util.concurrent.locks.ReentrantLock;


public class Service {

	private ReentrantLock lock;

	public Service(boolean isFair) {
		super();
		lock = new ReentrantLock(isFair);
	}

	public void serviceMethod() {
		try {
			System.out.println(lock.isHeldByCurrentThread());
			lock.lock();
			System.out.println(lock.isHeldByCurrentThread());
		} finally {
			lock.unlock();
		}
	}
}


package chapter04.section01.thread_4_1_12.project_1_lockMethodTest3.test2;

public class Run {

	public static void main(String[] args) throws InterruptedException {
		final Service service1 = new Service(true);
		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				service1.serviceMethod();
			}
		};
		Thread thread = new Thread(runnable);
		thread.start();
	}
}
/*
result:
false
true
*/

 

3) isLocked()
方法boolean isLocked()的作用是查詢此鎖定是否由任意執行緒保持

文件:

public boolean isLocked​()
Queries if this lock is held by any thread. This method is designed for use in 
monitoring of the system state, not for synchronization control.
Returns:
true if any thread holds this lock and false otherwise

舉例:

package chapter04.section01.thread_4_1_12.project_1_lockMethodTest3.test3;

import java.util.concurrent.locks.ReentrantLock;

public class Service {

	private ReentrantLock lock;

	public Service(boolean isFair) {
		super();
		lock = new ReentrantLock(isFair);
	}

	public void serviceMethod() {
		try {
			System.out.println(lock.isLocked());
			lock.lock();
			System.out.println(lock.isLocked());
		} finally {
			lock.unlock();
		}
	}
}


package chapter04.section01.thread_4_1_12.project_1_lockMethodTest3.test3;

public class Run {

	public static void main(String[] args) throws InterruptedException {
		final Service service1 = new Service(true);
		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				service1.serviceMethod();
			}
		};
		Thread thread = new Thread(runnable);
		thread.start();
	}
}
/*
result:
false
true
*/

 

(4) 方法lockInterruptibly(),tryLock()和tryLock(long timeout, TimeUnit unit)
的測試
1) lockInterruptibly()
方法void lockInterruptibly()的作用是: 如果當前執行緒未被中斷,則獲取鎖定,如果已經
被中斷,則出現異常。

文件:
https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/locks/ReentrantLock.html#lockInterruptibly

舉例:

package chapter04.section01.thread_4_1_13.project_1_lockInterruptiblyTest1;

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

public class Service {

	public ReentrantLock lock = new ReentrantLock();

	public void waitMethod(){
		try {
			lock.lock();
//			lock.lockInterruptibly();
			System.out.println("lock begin " 
			+ Thread.currentThread().getName());
			for (int i = 0; i < Integer.MAX_VALUE / 10; i++) {
				String newString = new String();
				Math.random();
			}
			System.out.println("lock   end " 
					+ Thread.currentThread().getName());
		} 
//		catch(InterruptedException e) {
//				System.out.println("執行緒"+Thread.currentThread().getName()+"進入catch~!");
//				e.printStackTrace();
//		}
		finally {
			if (lock.isHeldByCurrentThread()) {
				lock.unlock();
			}
		}
	}
}


package chapter04.section01.thread_4_1_13.project_1_lockInterruptiblyTest1;

public class Run {

	public static void main(String[] args) throws InterruptedException {
		final Service service = new Service();
		Runnable runnableRef = new Runnable() {
			@Override
			public void run() {
				service.waitMethod();
			}
		};

		Thread threadA = new Thread(runnableRef);
		threadA.setName("A");
		threadA.start();
		Thread.sleep(500);
		Thread threadB = new Thread(runnableRef);
		threadB.setName("B");
		threadB.start();
		threadB.interrupt();// 打標記
		System.out.println("main end!");
	}
}
/*
result:
lock begin A
main end!
lock   end A
lock begin B
lock   end B
執行緒B被interrupt設定中斷標記了,執行lock.lock()
不出現異常,正常執行

去掉註釋,將lock.lock()換成lock.lockInterruptibly()
result:
lock begin A
main end!
執行緒B進入catch~!
java.lang.InterruptedException
	at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(Unknown Source)
	at java.base/java.util.concurrent.locks.ReentrantLock.lockInterruptibly(Unknown Source)
	at chapter04.section01.thread_4_1_13.project_1_lockInterruptiblyTest1.Service.waitMethod(Service.java:13)
	at chapter04.section01.thread_4_1_13.project_1_lockInterruptiblyTest1.Run$1.run(Run.java:10)
	at java.base/java.lang.Thread.run(Unknown Source)
lock   end A
*/

 

2) tryLock()
方法boolean tryLock()的作用是,僅在呼叫時鎖定未被另一個執行緒保持的情況下,才獲取該
鎖定
文件:

public boolean tryLock​()
Acquires the lock only if it is not held by another thread at the time of invocation.
Acquires the lock if it is not held by another thread and returns immediately with the 
value true, setting the lock hold count to one. Even when this lock has been set to use 
a fair ordering policy, a call to tryLock() will immediately acquire the lock if it is 
available, whether or not other threads are currently waiting for the lock. This "barging" 
behavior can be useful in certain circumstances, even though it breaks fairness. 
If you want to honor the fairness setting for this lock, then use tryLock(0, TimeUnit.SECONDS) 
which is almost equivalent (it also detects interruption).
只有在呼叫時其他執行緒不持有鎖時才獲得鎖。如果鎖不是由另一個執行緒持有,則立即獲取該鎖,並返回值為true,將鎖持有
計數器設定為1.甚至當這個鎖被設定為使用公平順序政策,呼叫tryLock(),如果鎖可用立即獲得鎖,不論其他執行緒
還在等待此鎖。這種"協定"行為在某些情況下是有用的,即使它破壞了公平。如果你想要尊重這個鎖的公平設定,那麼
使用tryLock(0, TimeUnit.SECONDS)它幾乎是等價的(它也檢測中斷)

If the current thread already holds this lock then the hold count is incremented by one and 
the method returns true.
如果當前執行緒已經持有此鎖,則持有計數器將增加1,並且該方法返回true.

If the lock is held by another thread then this method will return immediately with the value false.
如果鎖被另一個執行緒持有,那麼該方法將立即返回未false

Specified by:
tryLock in interface Lock
Returns:
true if the lock was free and was acquired by the current thread, or the lock was already held 
by the current thread; and false otherwise

舉例:

package chapter04.section01.thread_4_1_13.project_3_tryLockTest;

import java.util.concurrent.locks.ReentrantLock;

public class Service {
	public ReentrantLock lock = new ReentrantLock();
	
	public void waitMethod() {
		if(lock.tryLock()) {
			System.out.println(Thread.currentThread().getName() + "獲得鎖");
		} else {
			System.out.println(Thread.currentThread().getName() + "沒有獲得鎖");
		}
	}
}


package chapter04.section01.thread_4_1_13.project_3_tryLockTest;

public class Run {

	public static void main(String[] args) throws InterruptedException {
		final Service service = new Service();

		Runnable runnableRef = new Runnable() {
			@Override
			public void run() {
				service.waitMethod();
			}
		};

		Thread threadA = new Thread(runnableRef);
		threadA.setName("A");
		threadA.start();
		Thread threadB = new Thread(runnableRef);
		threadB.setName("B");
		threadB.start();
	}
}
/*
result:
A獲得鎖
B沒有獲得鎖
*/

 

3) tryLock(long timeout, TimeUnit unit)
方法boolean tryLock(long timeout, TimeUnit unit)的作用是: 如果鎖定在給定等待時
間內沒有被另一個執行緒保持,且當前執行緒未被中斷,獲取該鎖定。


舉例:

package chapter04.section01.thread_4_1_13.project_4_tryLock_param;

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

public class Service {

	public ReentrantLock lock = new ReentrantLock();

	public void waitMethod() {
		try {
			if (lock.tryLock(3, TimeUnit.SECONDS)) {
				System.out.println("      " + Thread.currentThread().getName()
						+ "獲得鎖的時間:" + System.currentTimeMillis());
				Thread.sleep(10000);
			} else {
				System.out.println("      " + Thread.currentThread().getName()
						+ "沒有獲得鎖");
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			if (lock.isHeldByCurrentThread()) {
				lock.unlock();
			}
		}
	}
}


package chapter04.section01.thread_4_1_13.project_4_tryLock_param;

public class Run {

	public static void main(String[] args) throws InterruptedException {
		final Service service = new Service();

		Runnable runnableRef = new Runnable() {
			@Override
			public void run() {
				System.out.println(Thread.currentThread().getName()
						+ "呼叫waitMethod時間:" + System.currentTimeMillis());
				service.waitMethod();
			}
		};

		Thread threadA = new Thread(runnableRef);
		threadA.setName("A");
		threadA.start();
		Thread threadB = new Thread(runnableRef);
		threadB.setName("B");
		threadB.start();
	}
}
/*
result:
A獲得鎖
B沒有獲得鎖
*/