java.util.concurrent.locks.Lock(jdk1.5新增顯示鎖)
阿新 • • 發佈:2020-09-10
Lock是java.util.concurrent.locks下的一個介面,是從jdk1.5新增的顯示鎖
比較常用的實現類是ReentrantLock(可重入鎖)
CopyOnWriteArrayList內部使用了ReentrantLock
不安全的多人買票
// 售票 class Station implements Runnable { // 總票數 private int count = 10; @Override public void run() { while (true) { this.sale(); } } // 售票 private void sale() { if (count <= 0) { return; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " --> " + this.count--); } }
測試程式碼
Station beijing = new Station();
// 3個人買票
new Thread(beijing).start();
new Thread(beijing).start();
new Thread(beijing).start();
執行結果
Thread-0 --> 10 Thread-2 --> 9 Thread-1 --> 8 Thread-0 --> 7 Thread-2 --> 6 Thread-1 --> 5 Thread-0 --> 4 Thread-2 --> 3 Thread-1 --> 2 Thread-0 --> 1 Thread-2 --> 0 Thread-1 --> -1
使用ReentrantLock改進程式碼
// 售票 class Station implements Runnable { // 總票數 private int count = 10; // 標記位 private boolean flag = true; // 定義一個鎖 private final Lock lock = new ReentrantLock(); @Override public void run() { while (this.flag) { try { // 加鎖 lock.lock(); this.sale(); } catch (Exception e) { e.printStackTrace(); } finally { // 釋放鎖 lock.unlock(); } } } // 售票 private void sale() { if (this.count <= 0) { this.flag = false; return; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " --> " + this.count--); } }
測試程式碼
Station beijing = new Station();
// 3個人買票
new Thread(beijing).start();
new Thread(beijing).start();
new Thread(beijing).start();
執行結果
Thread-0 --> 10
Thread-0 --> 9
Thread-0 --> 8
Thread-0 --> 7
Thread-1 --> 6
Thread-1 --> 5
Thread-2 --> 4
Thread-2 --> 3
Thread-2 --> 2
Thread-2 --> 1
可以看出是排隊執行的
synchronized和Lock區別
- synchronized是隱式鎖,出了作用域自動釋放;Lock是顯示鎖,需要手動加鎖和釋放鎖
- synchronized有方法鎖和程式碼塊鎖;Lock只有程式碼塊鎖
- 使用Lock鎖,JVM將花費較少的時間來排程執行緒,效能更好
- Lock有更好的擴充套件性,提供了更多的子類