国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java多線程并發編程(互斥鎖Reentrant Lock)

Java多線程并發編程(互斥鎖Reentrant Lock)

2020-10-23 21:00hackeris Java教程

這篇文章主要介紹了ReentrantLock 互斥鎖,在同一時間只能被一個線程所占有,在被持有后并未釋放之前,其他線程若想獲得該鎖只能等待或放棄,需要的朋友可以參考下

Java 中的鎖通常分為兩種:

通過關鍵字 synchronized 獲取的鎖,我們稱為同步鎖,上一篇有介紹到:Java 多線程并發編程 Synchronized 關鍵字
java.util.concurrent(JUC)包里的鎖,如通過繼承接口 Lock 而實現的 ReentrantLock(互斥鎖),繼承 ReadWriteLock 實現的 ReentrantReadWriteLock(讀寫鎖)。
本篇主要介紹 ReentrantLock(互斥鎖)。

ReentrantLock(互斥鎖)

ReentrantLock 互斥鎖,在同一時間只能被一個線程所占有,在被持有后并未釋放之前,其他線程若想獲得該鎖只能等待或放棄。

ReentrantLock 互斥鎖是可重入鎖,即某一線程可多次獲得該鎖。

公平鎖 and 非公平鎖

?
1
2
3
4
5
6
7
public ReentrantLock() {
    sync = new NonfairSync();
  }
 
  public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
  }

由 ReentrantLock 的構造函數可見,在實例化 ReentrantLock 的時候我們可以選擇實例化一個公平鎖或非公平鎖,而默認會構造一個非公平鎖。

公平鎖與非公平鎖區別在于競爭鎖時的有序與否。公平鎖可確保有序性(FIFO 隊列),非公平鎖不能確保有序性(即使也有 FIFO 隊列)。

然而,公平是要付出代價的,公平鎖比非公平鎖要耗性能,所以在非必須確保公平的條件下,一般使用非公平鎖可提高吞吐率。所以 ReentrantLock 默認的構造函數也是“不公平”的。

一般使用

DEMO1:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class Test {
 
  private static class Counter {
 
    private ReentrantLock mReentrantLock = new ReentrantLock();
 
    public void count() {
      mReentrantLock.lock();
      try {
        for (int i = 0; i < 6; i++) {
          System.out.println(Thread.currentThread().getName() + ", i = " + i);
        }
      } finally {
          // 必須在 finally 釋放鎖
        mReentrantLock.unlock();
      }
    }
  }
 
  private static class MyThread extends Thread {
 
    private Counter mCounter;
 
    public MyThread(Counter counter) {
      mCounter = counter;
    }
 
    @Override
    public void run() {
      super.run();
      mCounter.count();
    }
  }
 
  public static void main(String[] var0) {
    Counter counter = new Counter();
    // 注:myThread1 和 myThread2 是調用同一個對象 counter
    MyThread myThread1 = new MyThread(counter);
    MyThread myThread2 = new MyThread(counter);
    myThread1.start();
    myThread2.start();
  }
}

DEMO1 輸出:

?
1
2
3
4
5
6
7
8
9
10
11
12
Thread-0, i = 0
Thread-0, i = 1
Thread-0, i = 2
Thread-0, i = 3
Thread-0, i = 4
Thread-0, i = 5
Thread-1, i = 0
Thread-1, i = 1
Thread-1, i = 2
Thread-1, i = 3
Thread-1, i = 4
Thread-1, i = 5

DEMO1 僅使用了 ReentrantLock 的 lock 和 unlock 來提現一般鎖的特性,確保線程的有序執行。此種場景 synchronized 也適用。

鎖的作用域

DEMO2:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class Test {
 
  private static class Counter {
 
    private ReentrantLock mReentrantLock = new ReentrantLock();
 
    public void count() {
      for (int i = 0; i < 6; i++) {
        mReentrantLock.lock();
        // 模擬耗時,突出線程是否阻塞
        try{
          Thread.sleep(100);
          System.out.println(Thread.currentThread().getName() + ", i = " + i);
        } catch (InterruptedException e) {
          e.printStackTrace();
        } finally {
            // 必須在 finally 釋放鎖
          mReentrantLock.unlock();
        }
      }
    }
 
    public void doOtherThing(){
      for (int i = 0; i < 6; i++) {
        // 模擬耗時,突出線程是否阻塞
        try {
          Thread.sleep(100);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " doOtherThing, i = " + i);
      }
    }
  }
  
  public static void main(String[] var0) {
    final Counter counter = new Counter();
    new Thread(new Runnable() {
      @Override
      public void run() {
        counter.count();
      }
    }).start();
    new Thread(new Runnable() {
      @Override
      public void run() {
        counter.doOtherThing();
      }
    }).start();
  }
}

DEMO2 輸出:

?
1
2
3
4
5
6
7
8
9
10
11
12
Thread-0, i = 0
Thread-1 doOtherThing, i = 0
Thread-0, i = 1
Thread-1 doOtherThing, i = 1
Thread-0, i = 2
Thread-1 doOtherThing, i = 2
Thread-0, i = 3
Thread-1 doOtherThing, i = 3
Thread-0, i = 4
Thread-1 doOtherThing, i = 4
Thread-0, i = 5
Thread-1 doOtherThing, i = 5

DEMO3:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public class Test {
 
  private static class Counter {
 
    private ReentrantLock mReentrantLock = new ReentrantLock();
 
    public void count() {
      for (int i = 0; i < 6; i++) {
        mReentrantLock.lock();
        // 模擬耗時,突出線程是否阻塞
        try{
          Thread.sleep(100);
          System.out.println(Thread.currentThread().getName() + ", i = " + i);
        } catch (InterruptedException e) {
          e.printStackTrace();
        } finally {
          // 必須在 finally 釋放鎖
          mReentrantLock.unlock();
        }
      }
    }
 
    public void doOtherThing(){
      mReentrantLock.lock();
      try{
        for (int i = 0; i < 6; i++) {
          // 模擬耗時,突出線程是否阻塞
          try {
            Thread.sleep(100);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          System.out.println(Thread.currentThread().getName() + " doOtherThing, i = " + i);
        }
      }finally {
        mReentrantLock.unlock();
      }
 
    }
  }
 
  public static void main(String[] var0) {
    final Counter counter = new Counter();
    new Thread(new Runnable() {
      @Override
      public void run() {
        counter.count();
      }
    }).start();
    new Thread(new Runnable() {
      @Override
      public void run() {
        counter.doOtherThing();
      }
    }).start();
  }
}

DEMO3 輸出:

?
1
2
3
4
5
6
7
8
9
10
11
12
Thread-0, i = 0
Thread-0, i = 1
Thread-0, i = 2
Thread-0, i = 3
Thread-0, i = 4
Thread-0, i = 5
Thread-1 doOtherThing, i = 0
Thread-1 doOtherThing, i = 1
Thread-1 doOtherThing, i = 2
Thread-1 doOtherThing, i = 3
Thread-1 doOtherThing, i = 4
Thread-1 doOtherThing, i = 5

結合 DEMO2 和 DEMO3 輸出可見,鎖的作用域在于 mReentrantLock,因為所來自于 mReentrantLock。

可終止等待

DEMO4:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
public class Test {
 
  static final int TIMEOUT = 300;
 
  private static class Counter {
 
    private ReentrantLock mReentrantLock = new ReentrantLock();
 
    public void count() {
      try{
        //lock() 不可中斷
        mReentrantLock.lock();
        // 模擬耗時,突出線程是否阻塞
        for (int i = 0; i < 6; i++) {
          long startTime = System.currentTimeMillis();
          while (true) {
            if (System.currentTimeMillis() - startTime > 100)
              break;
          }
          System.out.println(Thread.currentThread().getName() + ", i = " + i);
        }
      } finally {
        // 必須在 finally 釋放鎖
        mReentrantLock.unlock();
      }
    }
 
    public void doOtherThing(){
      try{
        //lockInterruptibly() 可中斷,若線程沒有中斷,則獲取鎖
        mReentrantLock.lockInterruptibly();
        for (int i = 0; i < 6; i++) {
          // 模擬耗時,突出線程是否阻塞
          long startTime = System.currentTimeMillis();
          while (true) {
            if (System.currentTimeMillis() - startTime > 100)
              break;
          }
          System.out.println(Thread.currentThread().getName() + " doOtherThing, i = " + i);
        }
      } catch (InterruptedException e) {
        System.out.println(Thread.currentThread().getName() + " 中斷 ");
      }finally {
        // 若當前線程持有鎖,則釋放
        if(mReentrantLock.isHeldByCurrentThread()){
          mReentrantLock.unlock();
        }
      }
    }
  }
 
  public static void main(String[] var0) {
    final Counter counter = new Counter();
    new Thread(new Runnable() {
      @Override
      public void run() {
        counter.count();
      }
    }).start();
    Thread thread2 = new Thread(new Runnable() {
      @Override
      public void run() {
        counter.doOtherThing();
      }
    });
    thread2.start();
    long start = System.currentTimeMillis();
    while (true){
      if (System.currentTimeMillis() - start > TIMEOUT) {
        // 若線程還在運行,嘗試中斷
        if(thread2.isAlive()){
          System.out.println(" 不等了,嘗試中斷 ");
          thread2.interrupt();
        }
        break;
      }
    }
  }
}

DEMO4 輸出:

?
1
2
3
4
5
6
7
8
Thread-0, i = 0
Thread-0, i = 1
Thread-0, i = 2
不等了,嘗試中斷
Thread-1 中斷
Thread-0, i = 3
Thread-0, i = 4
Thread-0, i = 5

線程 thread2 等待 300ms 后 timeout,中斷等待成功。

若把 TIMEOUT 改成 3000ms,輸出結果:(正常運行)

?
1
2
3
4
5
6
7
8
9
10
11
12
Thread-0, i = 0
Thread-0, i = 1
Thread-0, i = 2
Thread-0, i = 3
Thread-0, i = 4
Thread-0, i = 5
Thread-1 doOtherThing, i = 0
Thread-1 doOtherThing, i = 1
Thread-1 doOtherThing, i = 2
Thread-1 doOtherThing, i = 3
Thread-1 doOtherThing, i = 4
Thread-1 doOtherThing, i = 5

定時鎖

DEMO5:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
public class Test {
 
  static final int TIMEOUT = 3000;
 
  private static class Counter {
 
    private ReentrantLock mReentrantLock = new ReentrantLock();
 
    public void count() {
      try{
        //lock() 不可中斷
        mReentrantLock.lock();
        // 模擬耗時,突出線程是否阻塞
        for (int i = 0; i < 6; i++) {
          long startTime = System.currentTimeMillis();
          while (true) {
            if (System.currentTimeMillis() - startTime > 100)
              break;
          }
          System.out.println(Thread.currentThread().getName() + ", i = " + i);
        }
      } finally {
        // 必須在 finally 釋放鎖
        mReentrantLock.unlock();
      }
    }
 
    public void doOtherThing(){
      try{
        //tryLock(long timeout, TimeUnit unit) 嘗試獲得鎖
        boolean isLock = mReentrantLock.tryLock(300, TimeUnit.MILLISECONDS);
        System.out.println(Thread.currentThread().getName() + " isLock:" + isLock);
        if(isLock){
          for (int i = 0; i < 6; i++) {
            // 模擬耗時,突出線程是否阻塞
            long startTime = System.currentTimeMillis();
            while (true) {
              if (System.currentTimeMillis() - startTime > 100)
                break;
            }
            System.out.println(Thread.currentThread().getName() + " doOtherThing, i = " + i);
          }
        }else{
          System.out.println(Thread.currentThread().getName() + " timeout");
        }
      } catch (InterruptedException e) {
        System.out.println(Thread.currentThread().getName() + " 中斷 ");
      }finally {
        // 若當前線程持有鎖,則釋放
        if(mReentrantLock.isHeldByCurrentThread()){
          mReentrantLock.unlock();
        }
      }
    }
  }
 
  public static void main(String[] var0) {
    final Counter counter = new Counter();
    new Thread(new Runnable() {
      @Override
      public void run() {
        counter.count();
      }
    }).start();
    Thread thread2 = new Thread(new Runnable() {
      @Override
      public void run() {
        counter.doOtherThing();
      }
    });
    thread2.start();
  }
}

DEMO5 輸出:

?
1
2
3
4
5
6
7
8
Thread-0, i = 0
Thread-0, i = 1
Thread-0, i = 2
Thread-1 isLock:false
Thread-1 timeout
Thread-0, i = 3
Thread-0, i = 4
Thread-0, i = 5

tryLock() 嘗試獲得鎖,tryLock(long timeout, TimeUnit unit) 在給定的 timeout 時間內嘗試獲得鎖,若超時,則不帶鎖往下走,所以必須加以判斷。

ReentrantLock or synchronized

ReentrantLock 、synchronized 之間如何選擇?

ReentrantLock 在性能上 比 synchronized 更勝一籌。

ReentrantLock 需格外小心,因為需要顯式釋放鎖,lock() 后記得 unlock(),而且必須在 finally 里面,否則容易造成死鎖。
synchronized 隱式自動釋放鎖,使用方便。

ReentrantLock 擴展性好,可中斷鎖,定時鎖,自由控制。
synchronized 一但進入阻塞等待,則無法中斷等待。

原文鏈接:http://hackeris.me/2017/04/22/concurrent_series_4/

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 国内精品久久久久久中文字幕 | 一区二区三区在线不卡 | 精品国产成人在线 | 午夜午夜精品一区二区三区文 | 在线观看国产视频 | 亚洲品质自拍视频网站 | 欧美精品亚洲 | 日韩高清一区二区 | 日本黄色毛片 | 91亚洲国产成人久久精品网站 | 成人精品国产 | 一本亚洲| 欧美一区二区三区免费视频 | 国偷自产一区二区免费视频 | 国产成人99久久亚洲综合精品 | 国产精品第一区 | 99久久精品免费看国产一区二区三区 | 亚洲国产aⅴ成人精品无吗 黄色免费在线看 | 成人精品一区二区 | 欧美午夜一区二区 | 91九色在线 | 日韩视频区 | 日韩精品成人 | 欧美日韩一区二区中文字幕 | 国产精品久久精品 | 成人在线手机版视频 | 不用播放器的av | 午夜激情在线 | 在线毛片观看 | 免费成人高清在线视频 | 国产欧美日韩综合精品一区二区 | 国产黄色大全 | 成人免费毛片高清视频 | 91久久精品国产91久久性色tv | 欧美黑人狂躁日本寡妇 | 91精品国产91久久久久久最新 | 91av免费在线观看 | 亚洲一区二区久久 | 国产精品色哟哟哟 | 欧美黄视频在线观看 | 亚洲国产一区二区三区精品 |