1. 程式人生 > 其它 >多執行緒(四)鎖

多執行緒(四)鎖

多執行緒(四)鎖

目錄

死鎖

  • 一個同步塊同時擁有“兩個以上物件的鎖”時,就可能會發生“死鎖”的問題(相互等待對方的資源)

產生死鎖的條件

  • 以下死鎖的四個必要條件,只要想辦法其中的任意一個或者多個條件就可以避免死鎖的發生
  1. 互斥條件:一個資源每次只能被一個程序使用
  2. 請求與保持條件:一個程序因請求資源而阻塞時,對已獲得的資源保持不放
  3. 不剝奪條件:程序已獲得的資源,在未使用完之前,不能強制剝奪
  4. 迴圈等待條件:若干程序之間形成一種頭尾相接的迴圈等待資源關係

Lock鎖

  • 通過顯示定義同步鎖物件來實現同步。同步鎖使用Lock物件充當
  • ReentrantLock類實現了Lock

Lock鎖和synchronized鎖的區別

    • Lock是顯示鎖(手動)
    • synchronized是隱式鎖
    • Lock只有程式碼塊鎖
    • synchronized有程式碼塊鎖和方法鎖
    • Lock效能更好

程式碼例項

死鎖

  • 張三要鏡子,但是鏡子在李四手上,李四要口紅,但是口紅在張三手上
  • 死鎖,永遠不會停止
public class SXP10 {
    public static void main(String[] args) {
        Makeup g1=new Makeup(0,"張三");
        Makeup g2=new Makeup(1,"李四");
        g1.start();
        g2.start();
    }
}
//口紅
class Lipstick{

}
//鏡子
class Mirror{

}
class Makeup extends Thread{
    //需要的資源只有一份,用static來保證只有一份
    static Lipstick lipstick=new Lipstick();
    static Mirror mirror=new Mirror();
    int choice;
    String girlNmae;//使用化妝品的人
    Makeup(int choice,String girlNmae){
        this.choice=choice;
        this.girlNmae=girlNmae;
    }
    @Override
    public void run(){
        //化妝
        try {
            makeup();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    private  void makeup() throws InterruptedException {
        if(choice==0){
            synchronized (lipstick){//獲得口紅的鎖
                System.out.println(this.girlNmae+"獲得口紅的鎖");
                Thread.sleep(1000);
                synchronized (mirror){//1秒鐘之後獲得鏡子的鎖
                    System.out.println(this.girlNmae+"獲得鏡子的鎖");
                }
            }
        }else{
            synchronized (mirror) {//獲得鏡子的鎖
                System.out.println(this.girlNmae + "獲得鏡子的鎖");
                Thread.sleep(2000);
                synchronized (lipstick){//1秒鐘之後獲得口紅的鎖
                    System.out.println(this.girlNmae+"獲得口紅的鎖");
                }
            }
        }
    }
}

防止上述死鎖

public class SXP10 {
    public static void main(String[] args) {
        Makeup g1=new Makeup(0,"張三");
        Makeup g2=new Makeup(1,"李四");
        g1.start();
        g2.start();
    }
}
//口紅
class Lipstick{

}
//鏡子
class Mirror{

}
class Makeup extends Thread{
    //需要的資源只有一份,用static來保證只有一份
    static Lipstick lipstick=new Lipstick();
    static Mirror mirror=new Mirror();
    int choice;
    String girlNmae;//使用化妝品的人
    Makeup(int choice,String girlNmae){
        this.choice=choice;
        this.girlNmae=girlNmae;
    }
    @Override
    public void run(){
        //化妝
        try {
            makeup();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    private  void makeup() throws InterruptedException {
        if(choice==0){
            synchronized (lipstick){//獲得口紅的鎖
                System.out.println(this.girlNmae+"獲得口紅的鎖");
                Thread.sleep(1000);
            }
            synchronized (mirror){//1秒鐘之後獲得鏡子的鎖
                System.out.println(this.girlNmae+"獲得鏡子的鎖");
            }
        }else{
            synchronized (mirror) {//獲得鏡子的鎖
                System.out.println(this.girlNmae + "獲得鏡子的鎖");
            }
            Thread.sleep(2000);
            synchronized (lipstick){//1秒鐘之後獲得口紅的鎖
                System.out.println(this.girlNmae+"獲得口紅的鎖");
            }
        }
    }
}
//輸出:
張三獲得口紅的鎖
李四獲得鏡子的鎖
張三獲得鏡子的鎖
李四獲得口紅的鎖

Lock鎖

public class Sxp11 {
    public static void main(String[] args) {
        TestLock2 t1=new TestLock2();
        new Thread(t1).start();
        new Thread(t1).start();
        new Thread(t1).start();
    }
}
    class TestLock2 implements Runnable{
        int ticketNums=10;
        //定義lock鎖
        private final ReentrantLock lock=new ReentrantLock();

        @Override
        public void run() {
            while (true){
                try {
                    lock.lock();//加鎖
                    if(ticketNums>0){
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(ticketNums--);
                    }else {
                        break;
                    }
                }finally {
                    //解鎖
                    lock.unlock();
                }

            }
        }
    }
//輸出:
10
9
8
7
6
5
4
3
2
1