java学习第十八天 上午(Lock锁)

首先使用Synchronized同步代码块可以实现生产者和消费者之间每一次的完整步骤,就好比银行家算法中的取钱步骤,如果没有synchronized同步代码块,可能会出现取钱1次对总共的金额减少,但是还没有来的及打印出来剩余金额,第二个线程中第二个用户对同一个账户再次进行取款,取款结束未进行打印时线程二暂停,开始执行线程一的打印,会导致数据发生错乱。

为了解决这个问题,我们可以在synchronized的前提下。引入了wait()和notify()的方法,如果某个条件未达到时,该线程使用wait()方法进行等待,当线程2达到该条件,使用notify()进行通知其他线程,这样可以防止数据与实际问题不符合的情况。这种情况对应生产者和消费者,生产者生产商品,生产一次消费者取一次产品,消费者取一次生产者才能继续生产。(一生产者一消费者的问题)。

/*这种判断条件: 如果flag是食物有无的标识符,如果为true就说明还有商品,此时
生产者不工作,消费者开始工作,当吃完食物时,将标志符置为false,此时生产者进行工作*/
public void run() {
        for(int i=0;i<20;i++){
            synchronized (food){
                if(food.flag==false){
                    try {
                        food.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                food.setFood("屎");
                System.out.println(Thread.currentThread().getName()+"正在吃"+food.getFood()+"你看他吃的很舒服");
                food.notify();
                food.flag=false;

            }
        }
    }

如果我们面对(多生产者多消费者的问题),当判断条件还为if语句时如果没有达到我们想要的条件时,我们的思路是暂停该线程,notify()或者notifyAll()其他的线程。来进行继续执行,但是大家有没有想过这个问题,此时我暂停的只是一个生产者的线程,但是notify的是其他线程,是不是有可能也唤醒其他的生产者线程,如果我判断这个商品数量为10的时候,生产者线程就不生产了,但是我此时只是wait了一个生产者线程,随机唤醒其他线程,是不是有可能唤醒除了这个生产者线程的其他生产者线程?所以,此时我们就不能用这种方法进行修改了,我们需要用while的方法来对条件进行判断,不能用if条件进行判断了。

/*使用while进行判断*/
    public synchronized void creatfood( String foodname){
        while(list.size()==10){//通过while循环把所有的生产者线程全部的wait了
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        list.add(foodname);
        System.out.println(Thread.currentThread().getName()+"拉了一吨"+foodname+"\t目前的"+foodname+"有"+list.size()+"吨");
        this.notify();

    }

多生产者多消费者:面对这个问题我们还可以使用Lock锁,synchrnized是自动上锁和解锁,但是lock锁我们必须手动上锁,手动开锁,所以必须使用try catch fianlly语句,不管怎么样,finally里是开锁语句。所以在这个问题中,我们还可以使用锁,来对这个进行控制,面对多生产者和多消费者,我们还能够对锁增加两种情况来进行使用。

    private Lock lock=new ReentrantLock();//创建一个锁的对象
    Condition makecond=lock.newCondition();//锁对象中的生产者
    Condition eatcond=lock.newCondition();

 

创建好之后我们如何使用呢,只需要当遇到某个条件时指名道姓的告诉当某个锁,你们这种类型的稍微等一下,那么这种类型的都进入暂停的状态了,另一种类型的就当然可以运行了,同理,当另一种情况就时达到某种情况的时候,就告诉这种类型的锁。你们这种类型的锁需要等下,那么另一种锁便会开始运行。

    public  void creatfood( String foodname){
        lock.lock();
        try{
            while(list.size()==10){
                try {
                    makecond.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            list.add(foodname);
            System.out.println(Thread.currentThread().getName()+"拉了一吨"+foodname+"\t目前的"+foodname+"有"+list.size()+"吨");
            eatcond.signal();
        }finally {
            lock.unlock();
        }



    }

    public synchronized void eatfood(){
        lock.lock();
        try{
            while(list.size()==0){
                try {
                    eatcond.await();//如果没得了,吃的就等等
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            list.remove(0);
            System.out.println(Thread.currentThread().getName()+"吃了一口"+foodname+"\t目前的"+foodname+"有"+list.size()+"吨");
            makecond.signalAll();//如果吃了一次,就通知生产者
        }finally {
            lock.unlock();
        }


    }

使用LOCK锁 !!!!必须必须要try  catch finally语句来对锁进行手动的释放!!!111

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值