(五)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();

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值