1. 程式人生 > 實用技巧 >java.util.concurrent.locks.Lock(jdk1.5新增顯示鎖)

java.util.concurrent.locks.Lock(jdk1.5新增顯示鎖)

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有更好的擴充套件性,提供了更多的子類