在講重入鎖(ReentrantLock)之前,相信大家都synchronized很熟悉了,它也是同步控制的一個重要鎖,決定了一個線程
是否可以訪問臨界資源,同時synchronized配合Object.wait()和Object.notify()的配合使用起到了等待通知的作用。這裏如果
大家不是很熟悉,可以查閱資料熟悉一下synchronized的使用。那麼有synchronized這個鎖,爲什麼還要介紹ReentrantLock,
這肯定是有原因,接下來我就會介紹ReentrantLock比synchronized鎖的優點。再說到優點之前,我們先看看ReentrantLock的
基本使用。
(一)ReenrantLock的基本使用
public class ReenterLock implements Runnable{
public static ReentrantLock lock = new ReentrantLock();
public static int i =0;
@Override
public void run() {
for(int j = 0;j<10000;j++){
lock.lock();
try {
i++;
}
finally{
lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
ReenterLock t = new ReenterLock();
Thread t1 =new Thread(t);
Thread t2 =new Thread(t);
t1.start();t2.start();
t1.join();t2.join();
System.out.println(i);
}
}
通過上面代碼我們可以看到ReentrantLock的lock()和unlock()方法要配合try/finally語句塊來完成,這是ReentrantLock的語法風格,
lock.lock();
lock.lock();
try{
i++;
}finally{
lock.unlock();
lock.unlock();
}
在這種情況下,一個線程連續兩次獲得同一把鎖,是允許,如果不允許這麼操作,那麼同一個線程在第二次獲得鎖時,將會與自己(二)ReetrantLock的高級功能
- 可以中斷響應
public class ReenterLock implements Runnable{
public static ReentrantLock lock1 = new ReentrantLock();
public static ReentrantLock lock2 = new ReentrantLock();
int lock;
public ReenterLock(int lock){
this.lock = lock;
}
@Override
public void run() {
try{
if (lock == 1){
lock1.lockInterruptibly();
try{
Thread.sleep(500);
}catch(InterruptedException e){}
lock2.lockInterruptibly();}
else{
lock2.lockInterruptibly();
try{
Thread.sleep(500);
}catch(InterruptedException e){}
lock1.lockInterruptibly();
}
}catch(InterruptedException e){
e.printStackTrace();
}finally{
if(lock1.isHeldByCurrentThread())
lock1.unlock();
if(lock2.isHeldByCurrentThread())
lock2.unlock();
System.out.println(Thread.currentThread().getId()+":線程退出");
}
}
public static void main(String[] args) throws InterruptedException {
ReenterLock r1 = new ReenterLock(1);
ReenterLock r2 = new ReenterLock(2);
Thread t1 =new Thread(r1);
Thread t2 =new Thread(r2);
t1.start();t2.start();
Thread.sleep(1000);
t2.interrupt();
}
}
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:896)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1221)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:340)
at demo.ReenterLock.run(ReenterLock.java:29)
at java.lang.Thread.run(Thread.java:745)
10:線程退出
9:線程退出
- 鎖等待限時
public class ReenterLock implements Runnable{
public static ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
try{
if(lock.tryLock(5, TimeUnit.SECONDS))
Thread.sleep(6000);
else{
System.out.println("get this lock fialed");
}
}catch(InterruptedException e){
e.printStackTrace();
}finally{
if(lock.isHeldByCurrentThread())
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
ReenterLock t = new ReenterLock();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();t2.start();
}
}
在這裏,tryLock()方法接受兩個參數,一個表示等待時長,另外一個表示計時單位。這裏的單位爲秒,時長爲5,表示線程- 公平鎖
public class ReenterLock implements Runnable{
public static ReentrantLock fairlock = new ReentrantLock(true);//設置爲true開啓公平鎖,默認是false
@Override
public void run() {
while(true){
try{
fairlock.lock();
System.out.println(Thread.currentThread().getName()+"獲得鎖");
}finally{
fairlock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
ReenterLock t = new ReenterLock();
Thread t1 = new Thread(t,"Thread_1");
Thread t2 = new Thread(t,"Thread_2");
t1.start();t2.start();
}
}
上面代碼在通過ReentranLock(boolean fair)設置爲true開啓公平鎖,接下來看看結果:Thread_1獲得鎖
Thread_2獲得鎖
Thread_1獲得鎖
Thread_2獲得鎖
Thread_1獲得鎖
Thread_2獲得鎖
Thread_1獲得鎖
Thread_2獲得鎖
Thread_1獲得鎖
由於代碼有大量的輸出,這裏只截取部分進行說明。這個輸出結果中,很明顯可以看到,兩個線程是交替執行的。(三)Condition條件
如果大家知道Object.wait 和 Object.notify方法的話,那麼就能很容易理解Condition 了,它們的作用大致相同的。public class ReenterLock implements Runnable{
public static ReentrantLock lock = new ReentrantLock();
public static Condition condition = lock.newCondition();
@Override
public void run() {
try{
lock.lock();
condition.await();
System.out.println("Thread is going on");
}catch(InterruptedException e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
ReenterLock t = new ReenterLock();
Thread t1 = new Thread(t);
t1.start();
Thread.sleep(2000);
//通知線程t1繼續執行
lock.lock();
condition.signal();
lock.unlock();
}
}
代碼第三行,通過lock生成一個與之綁定的Condition對象。代碼condition.await(),要求線程Condition對象上進行等待。