(五)Lock锁的用法||Lock锁与 synchronized 关键字的区别

Lock锁的用法

Lock锁机制与 synchronized 关键字的区别


一、Lock锁的用法

Lock lock = new ReentrantLock();
lock.lock();
try{
//可能会出现线程安全的操作
}finally{
//一定在finally中释放锁
//也不能把获取锁在try中进行,因为有可能在获取锁的时候抛出异常
lock.unlock();
}

二、Lock锁机制与 synchronized 关键字的区别

  1. synchronized修饰的同步代码块其实自身是具有自动上锁、自动解锁功能的;
    Lock锁机制则是手动解锁,手动上锁的;

  2. 用synchronized修饰的同步代码块还有同步方法是有同步锁对象的;
    Lock锁机制是没有同步锁对象的;

  3. 因为synchronized修饰的同步代码块还有同步方法是具有锁对象的,因此,可以
    调用notify()、wait()、notifyAll()的方法;

    但是因为Lock锁机制是不具有锁对象的,因此是不可以去调用notify()、wait()、
    notifyAll()方法的;
    那么如果Lock锁机制一定要使用等待唤醒机制的话,在Java5之后,我们只能通过创建一个Condition类对象,然后通过该对象来调用await()、signal()、signAll()方法,而这几个方法的作用跟notify()、wait()、notifyAll()是一样功能的;

三、Condition用法

Condition的功能类似于在传统的线程技术中的Object.wait()和Object.notify()的功能。

Condition condition = lock.newCondition();
user. condition.await(); 类似wait
user. Condition. Signal() 类似notify

四、代码示例

共享资源源实体类

/**
 共享资源源实体类
 */
class UserInfo {
    public String userSex;
    public String userName;
    /**手动lock锁*/
    Lock lock= new ReentrantLock();
    /**Condition功能*/
    Condition condition=lock.newCondition();
    /**线程通讯标识
     * true:让生产者进行等待,消费者进行消费
     * false:生产者可以生产,消费者进行等待
     * */
    public boolean flag=false;
}

输入线程资源

public class InputThread extends Thread{
    private UserInfo user;
    //构造函数
    public InputThread (UserInfo user){
        this.user=user;
    }
    @Override
    public void run() {
        int count=0;
            while (true){
                //开始手动上锁
                user.lock.lock();

                try {
                    //当flag为true时(注意:在判断条件里if(user.flag)等价于if(user.flag==true))
                    if (user.flag) {
                        //让当前线程 从运行状态变为休眠状态,并且释放锁的资源
                        user.condition.await();
                    }
                    //1.当线程第一次运行时,flag为false,先进行生产
                    if(count==0){
                            user.userName="大圣";
                            user.userSex="男";
                        }else{
                            user.userName="小红";
                            user.userSex="女";
                        }
                    //计算奇数或者偶数公式
                    count=(count+1)%2;
                    //2.当第一个线程生产完的时候,把flag状态改为true,
                    // 即让生产者线程处于等待状态,让消费者进行读取
                    user.flag=true;
                    //唤醒当前等待的线程,否则你只能打印一条
                    user.condition.signal();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    //手动释放锁
                    user.lock.unlock();
                }

            }
    }
 }

输出线程资源

public class OutputThread extends Thread{

    private UserInfo user;
    //构造函数
    public OutputThread(UserInfo user){
        this.user=user;
    }
    @Override
    public void run() {
        while (true) {
            //开始手动上锁
            user.lock.lock();
            try {
                //当flag为false时(注意:在判断条件里if(!user.flag)等价于if(user.flag==false))
                if (!user.flag) {
                    //让当前线程 从运行状态变为休眠状态,并且释放锁的资源
                    user.condition.await();
                }
                //3.进来时,flag为true,消费者进行消费,生产者进行等待
                System.out.println("userName:"+user.userName+"----userSex:"+user.userSex);
                //4.消费者读取完后,把flag状态改为false,再去生产者那边生产,待在消费者这里也没用
                user.flag=false;
                //唤醒当前等待的线程,否则你只能打印一条
                user.condition.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //手动释放锁
                user.lock.unlock();
            }


        }
    }

}

运行代码:

 UserInfo user=new UserInfo();
        //构造方法就是在这里用的
        //两个线程共享同一变量
        InputThread it=new InputThread(user);
        OutputThread ot=new OutputThread(user);
        it.start();
        ot.start();

运行结果:
这里写图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值