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();
运行结果: