本身動手寫java鎖

一、LockSupport的park和unpark方法的基本使用,以及對線程中斷的響應性java

LockSupport是JDK中比較底層的類,用來建立鎖和其餘同步工具類的基本線程阻塞原語。java鎖和同步器框架的核心AQS:AbstractQueuedSynchronizer,就是經過調用LockSupport.park()和LockSupport.unpark()實現線程的阻塞和喚醒的。LockSupport很相似於二元信號量(只有1個許可證可供使用),若是這個許可尚未被佔用,當前線程獲取許可並繼續執行;若是許可已經被佔用,當前線程阻塞,等待獲取許可。注意:許可默認是被佔用的。框架

public static void main(String[] args)  {  ide

     LockSupport.park();  工具

     System.out.println("block.");  spa

線程

運行該代碼,能夠發現主線程一直處於阻塞狀態,不會輸出block.。由於許可默認是被佔用的,調用park()時獲取不到許可,因此進入阻塞狀態。須要注意的是,嘗試獲取許可證的是調用了 LockSupport.park()方法的線程。同步

LockSupport.unpark(Thread thread)方法須要傳入一個線程做爲參數,該方法的做用是容許做爲參數的線程獲取許可證,也就是喚醒做爲參數的線程。public static void main(String[] args)  {  string

     Thread thread = Thread.currentThread();  it

     LockSupport.unpark(thread);//釋放許可  io

     LockSupport.park();// 獲取許可  

     System.out.println("b");  

}

LockSupport是不可重入的,若是一個線程連續2次調用LockSupport.park(),那麼該線程必定會一直阻塞下去。

public static void main(String[] args) throws Exception  {  

    Thread thread = Thread.currentThread();  

    LockSupport.unpark(thread);  

    System.out.println("a");  

    LockSupport.park();  

    System.out.println("b");  

    LockSupport.park();  

    System.out.println("c");  

}

這段代碼打印出a和b,不會打印c,由於第二次調用park的時候,線程沒法獲取許可出現死鎖。

 

1.一、LockSupport對中斷的響應性

LockSupport.park()能響應中斷,也就是說A線程調用了LockSupport.park()方法被阻塞後,其餘線程調用了A線程的interrupt()方法給A線程發送中斷信號時,A線程的阻塞狀態會被中斷,繼續執行。固然了,調用了了某線程的interrupt()方法後,該線程的中斷狀態isInterrupted()會由false變爲true。

public static void main(String[] args) {
  Thread t = new Thread(new Runnable() {
    private int count = 0;
    @Override
    public void run() {
      long start = System.currentTimeMillis();
      long end = 0;
      while ((end - start) <= 1000) {
        count++;
        end = System.currentTimeMillis();
      }
      System.out.println("after 1 second.count=" + count);
      System.out.println("thread " + Thread.currentThread().isInterrupted());
      //等待或許許可
      LockSupport.park();
      System.out.println("thread over." + Thread.currentThread().isInterrupted());
    }
  });
  t.start();
  try {
    Thread.sleep(8000);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  System.out.println("向調用LockSupport.park()方法被阻塞的線程發送中斷信號");
  // 中斷線程
  t.interrupt();
  try {
    Thread.sleep(8000);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  System.out.println("main over");
}

最終線程會打印出thread over.true。這說明線程若是由於調用LockSupport.park()而阻塞的話,可以響應中斷請求(中斷狀態被設置成true),可是不會拋出InterruptedException。

 

二、Thread詳解

isInterrupted()  只獲取線程的中斷狀態,返回值爲線程的中斷狀態(每一個線程都有一箇中斷狀態標誌位,用於代表當前線程是否處於中斷狀態)

interrupted()  獲取線程的中斷狀態,並清空狀態(即若是線程的中斷狀態爲true,則將其設置爲false;若是線程的中斷狀態爲false,則什麼也不作),返回值爲清空狀態前線程的中斷狀態

通常調用Thread的interrupt()會有兩種處理方式:

(1)遇到一個低優先級的block狀態時,好比object.wait(),object.sleep(),object.join()致使線程阻塞,它會立馬觸發一個unblock解除阻塞,並在線程阻塞的位置拋出一個InterruptedException,此時當前線程的中斷狀態標誌爲false

(2)其餘狀況致使的線程阻塞,Thread的interrupt()僅僅是更新了線程的中斷狀態標誌位。而後線程繼續執行,固然你也能夠經過Thread.isInterrrupted()進行檢查,作相應的處理,好比也拋出InterruptedException或者是清理狀態,取消task等。 

相關文章
相關標籤/搜索