《JAVA300集》多线程_并发协作-day22

目录

一、死锁

死锁示例

避免死锁

二、线程协作-生产者消费者模式理论

三、管程法

四、信号灯法


一、死锁

死锁的概念:多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能进行,而导致多个线程都在等待对方释放资源,而都停止执行的现象。

某一个同步块同时拥有"两个以上对象的锁"时,就可能发生“死锁”的问题。

死锁示例

package Thread;

/*
* 死锁现象
* */
public class DeadLock {
    public static void main(String[] args) {
        MakeUp gir1 = new MakeUp(0,"小蒋");
        MakeUp gir2 = new MakeUp(1,"小机智");
        gir1.start();
        gir2.start();
    }
}

//口红
class Lipstick{
}

//镜子
class Mirror{
}

class MakeUp  extends Thread{
    static Lipstick lipstick = new Lipstick(); //静态只有一份对象
    static Mirror mirror = new Mirror();

    int choice;
    String girl;
    public MakeUp(int choice,String girl) {
        this.choice = choice;
        this.girl = girl;
    }

    @Override
    public void run() {
        //化妆
        makeup();
    }
    //相互持有对方的对象锁,可能造成死锁
    private void makeup(){
        if(choice==0){
            synchronized (lipstick){
                System.out.println(this.girl+"获得口红");
                //1秒后想拥有镜子的锁
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (mirror){
                    System.out.println(this.girl+"获得镜子");
                }
            }
        }else{
            synchronized (mirror){
                System.out.println(this.girl+"获得镜子");
                //2秒后想拥有口红的锁
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lipstick){
                    System.out.println(this.girl+"获得口红");
                }
            }
        }
    }
}

避免死锁

package Thread;

/*
* 解除死锁现象-避免锁套锁
* */
public class DeadLock {
    public static void main(String[] args) {
        MakeUp gir1 = new MakeUp(0,"小蒋");
        MakeUp gir2 = new MakeUp(1,"小机智");
        gir1.start();
        gir2.start();
    }
}

//口红
class Lipstick{
}

//镜子
class Mirror{
}

class MakeUp  extends Thread{
    static Lipstick lipstick = new Lipstick(); //静态只有一份对象
    static Mirror mirror = new Mirror();

    int choice;
    String girl;
    public MakeUp(int choice,String girl) {
        this.choice = choice;
        this.girl = girl;
    }

    @Override
    public void run() {
        //化妆
        makeup();
    }
    //避免锁套锁!一个锁中尽量不要有第二个锁,可以两个锁并列。
    private void makeup(){
        if(choice==0){
            synchronized (lipstick){
                System.out.println(this.girl+"获得口红");
                //1秒后想拥有镜子的锁
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            synchronized (mirror){
                System.out.println(this.girl+"获得镜子");
            }
        }else{
            synchronized (mirror){
                System.out.println(this.girl+"获得镜子");
                //2秒后想拥有口红的锁
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            synchronized (lipstick){
                System.out.println(this.girl+"获得口红");
            }
        }
    }
}

二、线程协作-生产者消费者模式理论

生产者消费者模式主要解决的是线程通信问题

生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件。

强调: wait() 会释放锁!

三、管程法

四个类:生产者、消费者、缓冲区、馒头

package cooperation;

/*
* 协作模型:生产者消费者实现
* 管程法
* */
public class CoTest01 {
    public static void main(String[] args) {
        SynContainer container = new SynContainer();
        new Productor(container).start();
        new Consumer(container).start();
    }
}

//生产者
class Productor extends Thread{
    SynContainer container;
    public Productor(SynContainer container) {
        this.container = container;
    }

    @Override
    public void run() {
        //生产
        for(int i=0;i<15;i++){
            //生产馒头时间
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            container.push(new Steamedbun(i));
            System.out.println("生产 第 "+i+" 个馒头");
        }
    }
}
//消费者
class Consumer extends Thread{
    SynContainer container;
    public Consumer(SynContainer container) {
        this.container = container;
    }

    @Override
    public void run() {
        //消费
        for(int i=0;i<15;i++){
            //消费者购买馒头时间
            try {
                Thread.sleep(250);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("消费 第 "+container.pop().getId()+" 个馒头");
        }
    }
}
//缓冲区
class SynContainer{
    Steamedbun[] buns = new Steamedbun[10]; //数组长度等于10,0-9
    int count = 0; //计数器
    //存储(生产)
    public synchronized void push(Steamedbun bun){
        //有空间的时候才可以生产
        if(count == buns.length){
            try {
                this.wait();  //线程阻塞,消费者通知生产时接触阻塞
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        buns[count] = bun;
        count++;
        this.notifyAll(); //目的:唤醒消费的wait
    }
    //获取(消费)
    public synchronized Steamedbun pop(){
        //有货的时候才可以消费
        if(count==0){
            try {
                this.wait();  //线程阻塞,生产者通知消费者时接触阻塞
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        count--;
        Steamedbun bun = buns[count];
        this.notifyAll(); //目的:唤醒生产的wait
        return bun;
    }

}
//馒头
class Steamedbun{
    private int id;

    public Steamedbun(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

}

四、信号灯法

红绿灯用真假表示

package cooperation;
/*
 * 协作模型:生产者消费者实现
 * 红绿灯法
 * */
public class CoTest02 {
    public static void main(String[] args) {
        Tv tv = new Tv();
        new Player(tv).start();
        new Watcher(tv).start();
    }
}
//生产者 演员
class Player extends Thread{
    Tv tv;

    public Player(Tv tv) {
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i=0;i<20;i++){
            if(i%2==0){
                this.tv.play("奇葩说");
            }else{
                this.tv.play("广告广告");
            }
        }
    }
}
//消费者 观众
class Watcher extends Thread{
    Tv tv;

    public Watcher(Tv tv) {
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i=0;i<20;i++){
            tv.watch();
        }
    }
}
//同一个资源 电视
class Tv{
    String voice;
    //信号灯
    //T 表示演员表演,观众等待
    //F 表示观众观看,演员等待
    boolean flag = true;

    //表演
    public synchronized void play(String voice){
        //演员等待
        if(!flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("表演了: "+voice);
        this.voice = voice;
        //唤醒观众
        this.notifyAll();
        this.flag=!this.flag;
    }

    //观看
    public synchronized void watch(){
        //观众等待
        if(flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("听到了: "+voice);
        this.notifyAll();
        this.flag=!this.flag;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值