Lock對象鎖(顯式鎖)第一篇實例

除了使用關鍵字 synchronized 支持的隱式鎖(對象的內置鎖)外,Concurrency API 支持由 Lock 接口指定的各類顯示鎖。顯示鎖能控制更細的粒度,所以也有更好的性能,在邏輯上也比較清晰。安全

標準 JDK中提供了多種顯示鎖的實現,將在下面的章節中進行介紹異步

 

直接上代碼ide

例子1:性能

public class SyncSameObjectTest1 implements Runnable{this

public void lord1(){.net

      try {線程

         Thread.sleep(2000);對象

  System.out.println("線程:"+Thread.currentThread().getName()+"運行時間:"+System.currentTimeMillis());接口

      } catch (Exception e) {get

      }

   }

//聲明顯示鎖

   private Lock lock =new ReentrantLock();

/* 這裏將Lock做爲線程變量,使得每次建立線程都建立一個Lock對象(對象鎖若是不是同一個對象就能異步執行,互不影響)。

    * 注意使用Lock鎖的時候,必定要包裹在try catch finally裏,使得出現運行期異常的時候,鎖可以釋放!*/

public void run(){

         try {

            lock.lock();//開始鎖定

            lord1();

         } catch (Exception e) {

           

         }finally{

          lock.unlock();//釋放鎖     

  }

}

public static void main (String args[]){

      try {

         ExecutorService eService = Executors.newCachedThreadPool();

         System.out.println("任務開始lock顯示鎖");

         for (int i = 0; i < 3; i++) {

            eService.submit(new SyncSameObjectTest1());

         }

         TimeUnit.SECONDS.sleep(10);

         System.out.println("任務執行結束");

         eService.shutdown();

      } catch (Exception e) {

      }

   }

}

 

這裏採用線程池去啓動線程,每次啓動線程都是新的線程,從結果能夠看到,Lock鎖三個線程是異步執行的,相互不影響。形成這種緣由是由於對象是不同的。

 

改造下試試:

例子2:

public class SyncSameObjectTest1 implements Runnable{

   private  Lock lock;

   public void lord1(){

      try {

         Thread.sleep(2000);

  System.out.println("線程:"+Thread.currentThread().getName()+"運行時間:"+System.currentTimeMillis());

      } catch (Exception e) {

      }

   }

   public SyncSameObjectTest1(Lock lock){

      this.lock=lock;

   }

   public SyncSameObjectTest1(){

   }

public void run(){

         try {

            lock.lock();//開始鎖定

            lord1();

         } catch (Exception e) {

            lock.unlock();//釋放鎖

         }finally{

            lock.unlock();

         }

      }

   public static void main (String args[]){

       Lock lock =new ReentrantLock();

 

      try {

         ExecutorService eService = Executors.newCachedThreadPool();

         System.out.println("任務開始lock顯示鎖");

         for (int i = 0; i < 3; i++) {

            eService.submit(new SyncSameObjectTest1(lock));

         }

         TimeUnit.SECONDS.sleep(10);

         System.out.println("任務執行結束");

         eService.shutdown();

      } catch (Exception e) {

      }

   }

}

這裏在main裏面實例化一個鎖(或者同一對象調用),線程實例化的時候,將該鎖(同一個對象)傳進去,已是同步運行了。說明了Lock顯式鎖是對象鎖。看運行順序及時間可知

任務開始lock顯示鎖

線程:pool-1-thread-1運行時間:1514537154767

線程:pool-1-thread-2運行時間:1514537156767

線程:pool-1-thread-3運行時間:1514537158767

任務執行結束

當第一個任務獲取鎖時,第二個任務獲取鎖的狀態信息:

 

例子3:

lock顯示鎖 鎖用一個對象調用與synchronized隱式鎖同一對象結果一致

public class SynchronizedTest {
    public static void main(String[] args) {
        //線程數
        int threadNum = 5;
        final Syn syn = new Syn();
        Thread[] threads = new Thread[threadNum];
        //記錄運行時間
        long l = System.currentTimeMillis();
        for (int i = 0; i < threadNum; i++) {
            threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 100000; j++) {
                        syn.increase();
                    }
                }
            });
            threads[i].start();
        }
        //等待全部線程結束
        try {
            for (int i = 0; i < threadNum; i++)
                threads[i].join(); 
            //main線程要等到threads[5]線程運行結束後,纔會往下執行輸出。若是不加threads[i].join(),
            //main線程和threads[i]線程是並行的。而加上threads[i].join(),程序就變成是順序執行了。
            //咱們在用到join()的時候,一般都是main線程等到其餘多個線程執行完畢後再繼續執行。其餘多個線程之間並不須要互相等待。

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(syn + " : " + (System.currentTimeMillis() - l) + "ms");
    }
}

class Syn {
    private  int count = 0;
    private Lock lock = new ReentrantLock();

    //利用synchronized
    public void increase() {
        synchronized (this) {
            count++;
        }
    }

    //利用ReentrantLock類同步
    public void increaseLock() {
        lock.lock();
        count++;
        lock.unlock();
    }
    //volatile   不是線程安全的  不保證原子性
    public void increaseVolatile() {
        count = count + 1;
    }

    @Override     public String toString() {         return String.valueOf(count);     } } 結果:500000 : 20ms

相關文章
相關標籤/搜索