死锁和Lock锁

死锁

  

//死锁:多个线程互相抱着对方需要的资源,然后形成僵持
public class DeadLock {

    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 grilName; //使用化妆品的人

    public Makeup(int choice, String grilName) {
        this.choice = choice;
        this.grilName = grilName;
    }

    @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.grilName+"获得口红的锁");
                Thread.sleep(1000);
            }
            synchronized(mirror){
                System.out.println(this.grilName+"获得镜子的锁");
            }
        }else {
            synchronized(mirror){//获得镜子锁
                System.out.println(this.grilName+"获得镜子的锁");
                Thread.sleep(2000);
            }
            synchronized (lipstick){
                System.out.println(this.grilName+"获得口红的锁");
            }
        }
    }
}

死锁避免方法:

产生死锁的4个必要条件
    1.互斥条件:一个资源每次只能被一个进程使用。(例子里如果都想拿口红镜子的话就会死锁)
    2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。(例子里如:拿了镜子后不放还想拿口红)
    3.不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。(例子里 如我拿着镜子你也不能抢)
    4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。(你想要我的我想要你的)

以上列出了死锁的四个必要条件,我们只要想办法破其中的任意一个或多个条件就可以避免死锁方生。

 Lock(锁)

import java.util.concurrent.locks.ReentrantLock;

public class TestLock {

    public static void main(String[] args) {

        TestLock2 testLock2=new TestLock2();
        new Thread(testLock2,"学生").start();
        new Thread(testLock2,"老师").start();
        new Thread(testLock2,"黄牛党").start();

    }

}

class  TestLock2 implements Runnable{

    int ticketNums=10;

    ReentrantLock lock=new ReentrantLock();

    @Override
    public void run() {
        while (true){

            try {
                lock.lock();     //枷锁
                if(ticketNums<1){
                    break;
                } else {
                    System.out.println(Thread.currentThread().getName()+"拿到了第"+ticketNums--+"张票");
                }

            }finally {
                lock.unlock();  //解锁
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

两者对比

synchronized与lock的对比
1.Lock是显示锁(手动开启和关闭锁,别忘了关闭锁)synchronized是隐式锁,出了作用域自动释放。
2.Lock只有代码块锁,synchronized有代码块锁和方法锁。
3.使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且具有更好的扩展性(提供更多的子类)
4.优先使用顺序:
    Lock>同步代码块(已经进入了方法体,分配了相应资源)>同步方法(在方法体之外)

 

posted @ 2022-02-18 23:49  十三加油哦  阅读(40)  评论(0)    收藏  举报