Lock鎖

傳統(tǒng)的Synchronized鎖

線程就是一個單獨的資源類,它沒有任何的附屬操作!
先看不加Synchronized多線程并發(fā)下的買票問題:

public class SaleTicket {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        //并發(fā),多個線程操作同一個資源類,將類丟入線程。
        new Thread(()->{
                for (int i = 1; i < 40; i++){
                    ticket.sale();
                }
            },"A").start();

        new Thread(()->{
                for (int i = 1; i < 40; i++){
                    ticket.sale();
                }
            },"B").start();

        new Thread(()->{
                for (int i = 1; i < 40; i++){
                    ticket.sale();
                }
            },"C").start();
    }
}

class Ticket{
    /*票數(shù)*/
    private int number = 30;

    /*買票的方式*/
    public void sale(){
        if (number > 0){
            System.out.println(Thread.currentThread().getName()+"賣出了第"+(number--)+"張,還剩"+number+"張。");
        }

    }
}

運行結果:

A賣出了第30張,還剩29張。
A賣出了第29張,還剩28張。
A賣出了第28張,還剩27張。
A賣出了第27張,還剩26張。
A賣出了第26張,還剩25張。
A賣出了第25張,還剩24張。
A賣出了第24張,還剩23張。
A賣出了第23張,還剩22張。
A賣出了第22張,還剩21張。
A賣出了第21張,還剩20張。
A賣出了第20張,還剩19張。
A賣出了第19張,還剩18張。
A賣出了第18張,還剩17張。
C賣出了第16張,還剩15張。
C賣出了第15張,還剩14張。
C賣出了第14張,還剩13張。
C賣出了第13張,還剩12張。
C賣出了第12張,還剩11張。
C賣出了第11張,還剩10張。
C賣出了第10張,還剩9張。
C賣出了第9張,還剩8張。
C賣出了第8張,還剩7張。
C賣出了第7張,還剩6張。
C賣出了第6張,還剩5張。
C賣出了第5張,還剩4張。
C賣出了第4張,還剩3張。
C賣出了第3張,還剩2張。
C賣出了第2張,還剩1張。
C賣出了第1張,還剩0張。
B賣出了第17張,還剩16張。

Process finished with exit code 0

很明顯可以看到,多個線程操作一個資源類的時候,會出現(xiàn)搶占的情況,導致運行結果不是我們想要看到的那樣,所以為保證線程同步安全,傳統(tǒng)方式我們會在資源類中加入Synchronized鎖以達到我們保證線程同步安全的目的。

/**
     * synchronized 本質(zhì):隊列、鎖*/
    public synchronized void sale(){
        if (number > 0){
            System.out.println(Thread.currentThread().getName()+"賣出了第"+(number--)+"張,還剩"+number+"張。");
        }

    }

使用Synchronized鎖后的運行結果:

A賣出了第30張,還剩29張。
A賣出了第29張,還剩28張。
A賣出了第28張,還剩27張。
A賣出了第27張,還剩26張。
A賣出了第26張,還剩25張。
A賣出了第25張,還剩24張。
A賣出了第24張,還剩23張。
A賣出了第23張,還剩22張。
A賣出了第22張,還剩21張。
A賣出了第21張,還剩20張。
A賣出了第20張,還剩19張。
A賣出了第19張,還剩18張。
A賣出了第18張,還剩17張。
A賣出了第17張,還剩16張。
A賣出了第16張,還剩15張。
A賣出了第15張,還剩14張。
A賣出了第14張,還剩13張。
A賣出了第13張,還剩12張。
A賣出了第12張,還剩11張。
A賣出了第11張,還剩10張。
B賣出了第10張,還剩9張。
B賣出了第9張,還剩8張。
B賣出了第8張,還剩7張。
B賣出了第7張,還剩6張。
B賣出了第6張,還剩5張。
B賣出了第5張,還剩4張。
B賣出了第4張,還剩3張。
B賣出了第3張,還剩2張。
B賣出了第2張,還剩1張。
B賣出了第1張,還剩0張。

Process finished with exit code 0

Lock鎖


基本實現(xiàn)類,常用ReentrantLock可重入鎖



ReentrantLock有兩個構造方法,無參構造默認非公平鎖,可以允許插隊;有參構造可以傳入一個Boolean值進行判斷,若為true,則是公平鎖,不允許插隊,先來的先執(zhí)行!



使用Lock鎖的買票例子:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SaleTicket02 {
    public static void main(String[] args) {
        Ticket02 ticket = new Ticket02();
        //并發(fā),多個線程操作同一個資源類,將類丟入線程。
        new Thread(()->{
                for (int i = 1; i < 40; i++){
                    ticket.sale();
                }
            },"A").start();

        new Thread(()->{
                for (int i = 1; i < 40; i++){
                    ticket.sale();
                }
            },"B").start();

        new Thread(()->{
                for (int i = 1; i < 40; i++){
                    ticket.sale();
                }
            },"C").start();
    }
}

/**
 * Lock三部曲
 * 1.new ReentrantLock()
 * 2.lock.lock() 加鎖;
 * 3.finally ==> lock.unlock() 解鎖*/
class Ticket02{
    /*票數(shù)*/
    private int number = 30;

    //Lock鎖
    Lock lock = new ReentrantLock();

    /*買票的方式*/
    public void sale(){

        //加鎖
        lock.lock();

        try {
            //業(yè)務代碼
            if (number > 0){
                System.out.println(Thread.currentThread().getName()+"賣出了第"+(number--)+"張,還剩"+number+"張。");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //解鎖
            lock.unlock();
        }

    }
}

Synchronized與Lock的區(qū)別

  • synchronized 是內(nèi)置的Java關鍵字,Lock 是一個Java類。
  • synchronized 無法判斷獲取鎖的狀態(tài),Lock 可以判斷是否獲取到了鎖。
  • synchronized 會自動釋放鎖,Lock 必須要手動釋放鎖,若不釋放鎖,會死鎖!
  • synchronized 線程A(獲得鎖,阻塞),線程B(等待,一直等待);Lock 不一定會等待下去,可以用lock.tryLock()嘗試獲取鎖。
  • synchronized 默認可重入,不可以中斷的,非公平;Lock 默認可重入,可以進行判斷鎖,非公平(可以進行設置)。
  • synchronized 適合鎖少量的代碼同步問題;Lock 適合鎖大量的同步代碼!
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
禁止轉載,如需轉載請通過簡信或評論聯(lián)系作者。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容