Lock锁的用法
Lock锁机制与 synchronized 关键字的区别
一、Lock锁的用法
Lock lock = new ReentrantLock();
lock.lock();
try{
//可能会出现线程安全的操作
}finally{
//一定在finally中释放锁
//也不能把获取锁在try中进行,因为有可能在获取锁的时候抛出异常
lock.unlock();
}
二、Lock锁机制与 synchronized 关键字的区别:
synchronized修饰的同步代码块其实自身是具有自动上锁、自动解锁功能的;
Lock锁机制则是手动解锁,手动上锁的;用synchronized修饰的同步代码块还有同步方法是有同步锁对象的;
Lock锁机制是没有同步锁对象的;因为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();
运行结果: