学习笔记——JAVA线程<5>线程的死锁

死锁:过多的同步容易造成死锁
使用同一份资源谁都不放手就锁住了
模拟死锁

package study;

/**
 * 模拟死锁
 * @author http://blog.csdn.net/thewaiting/
 *
 */

public class ThreadDome {
    public static void main(String[] args) {
        Object goods = new Object();
        Object money = new Object();
        Test t1 = new Test(goods, money);
        Test2 t2 = new Test2(goods, money);
        Thread proxy = new Thread(t1);
        Thread proxy2 = new Thread(t2);
        proxy.start();
        proxy2.start();
    }
}

class Test implements Runnable {
    Object goods = new Object();
    Object money = new Object();

    public Test(Object goods, Object money) {
        super();
        this.goods = goods;
        this.money = money;
    }

    @Override
    public void run() {
        while (true) {
            test();
        }
    }

    private void test() {
        synchronized (goods) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (money) {

            }

        }
        System.out.println("给钱");
    }
}

class Test2 implements Runnable {
    Object goods;
    Object money;

    public Test2(Object goods, Object money) {

        this.goods = goods;
        this.money = money;
    }

    @Override
    public void run() {
        while (true) {
            test();
        }
    }

    private void test() {
        synchronized (money) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (goods) {

            }

        }
        System.out.println("给货");
    }
}

生产者消费者(也成有限缓冲问题)模式解决死锁
先生产 后消费
生产者在缓冲区满时休眠(要么干脆放弃数据)等到下次消费者消耗缓冲区的数据的时候,生产者才能被唤醒开始往缓冲区添加数据。
消费者在缓冲区空时休眠,等到生产者往缓冲区添加数据再唤醒消费者。
通常的方法:信号灯法,管程等
如果解决方法不够完善则容易出现死锁情况
出现死锁时连个线程都会陷入休眠,等待对方唤醒自己

首先模拟一下

package study;
//测试
public class Text {

    public static void main(String[] args) {
        //共同的资源
        ThreadDome2 t = new ThreadDome2();
        //多线程  同时使用资源t
        Production p = new Production(t);
        Consume c = new Consume(t);

        new Thread(p).start();
        new Thread(c).start();      
    }

}
运行结果
生产 生产 生产 生产 生产 生产 生产 生产 生产 生产 生产 生产 生产 生产 生产 生产 生产 生产 生产 生产 
package study;
/**
 * 
 * @author http://blog.csdn.net/thewaiting/
 *
 */

public class ThreadDome2 {
    private String resource;
    public void production(String resource) {
        this.resource =resource;

    }
    public void  consume() {
        System.out.print(resource+" ");
    }
}
/**
 * 生产者
 * @author http://blog.csdn.net/thewaiting/
 *
 */
class Production implements Runnable{
    private ThreadDome2 t;//资源

    public Production(ThreadDome2 t) {
        super();
        this.t = t;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            if (0==i%2) {
                t.production("生产/被2整除");
            }else {
                t.production("生产");
            }

        }

    }
}
/**
 * 消费者
 * @author http://blog.csdn.net/thewaiting/
 *
 */
class Consume implements Runnable{
    private ThreadDome2 t;

    public Consume(ThreadDome2 t) {
        super();
        this.t = t;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            t.consume();        
        }

    }
}

信号灯法

唤醒:
notify() 唤醒在此对象监视器上等待的单个线程
notifyAll() 唤醒在此对象监视器上等待的所有线程
等待:
wait() 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。等待会释放锁sleep()不是释放锁*
以上方法要与同步一起使用,没有同步则无法等待

修改ThreadDome2 代码

package study;
/**
 * 使用生产者消费者模式
 * 信号灯法
 * @author http://blog.csdn.net/thewaiting/
 *
 */

public class ThreadDome2 {
    private String resource;
    //信号灯
    //当flag为true时生产者生产,消费者等待,生产完成后通知消费者
    //当flag为false消费者时生产,生产者等待,消费完成后通知生产者
    private boolean flag = true;
    public synchronized void production(String resource) throws InterruptedException {
        if (!flag) {//生产者等待
            this.wait();
        }
        //开始生产
        Thread.sleep(500);//模拟生产时间   放大错误的概率
        //生产完毕
        this.resource =resource;
        //通知消费
        this.notify();
        //生产者停下
        this.flag = false;
    }
    public synchronized void  consume() throws InterruptedException {
        if (flag) {//消费者等待
            this.wait();
        }
        //开始消费
        Thread.sleep(200);//模拟消费时间   放大错误的概率
        System.out.print(resource+" ");
        //消费完毕
        //通知生产者
        this.notify();
        //消费停止
        this.flag = true;
    }
}
运行结果
生产/被2整除 生产 生产/被2整除 生产 生产/被2整除 生产 生产/被2整除 生产 生产/被2整除 生产 生产/被2整除 生产 生产/被2整除 生产 生产/被2整除 生产 生产/被2整除 生产 生产/被2整除 生产 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值