Lock的使用
Posted xiazhenbin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lock的使用相关的知识,希望对你有一定的参考价值。
4.1 使用ReentrantLock类
在JKD1.5中,新增加了ReentrantLock类也能达到和synchronized关键字同样的效果,并且在扩展功能上更加强大,如嗅探锁定,多路分支通知等功能,在使用上也比synchronized更加灵活。
package ReentrantLock; /* * lock.lock() 代码的线程持有了“对象监视器”,其他线程只有等待锁被释放时再次争抢 */ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class t1 { public static void main(String[] args) throws InterruptedException { MyService service = new MyService(); MyThreadA a1 = new MyThreadA(service); a1.setName("A"); a1.start(); MyThreadAA a2 = new MyThreadAA(service); a2.setName("AA"); a2.start(); Thread.sleep(100); MyThreadB a3 = new MyThreadB(service); a3.setName("B"); a3.start(); MyThreadBB a4 = new MyThreadBB(service); a4.setName("BB"); a4.start(); } } class MyService { private Lock lock = new ReentrantLock(); public void MethodA() { try { lock.lock(); System.out.println("methodA begin ThreadName=" + Thread.currentThread().getName() + " time=" + System.currentTimeMillis()); Thread.sleep(5000); System.out.println("methodA end ThreadName=" + Thread.currentThread().getName() + " time=" + System.currentTimeMillis()); }catch (InterruptedException e) { // TODO: handle exception e.printStackTrace(); }finally{ //不管是否发生异常,该代码块都执行 lock.unlock(); } } public void MethodB() { try { lock.lock(); System.out.println("methodB begin ThreadName=" + Thread.currentThread().getName() + " time=" + System.currentTimeMillis()); Thread.sleep(5000); System.out.println("methodB end ThreadName=" + Thread.currentThread().getName() + " time=" + System.currentTimeMillis()); }catch (InterruptedException e) { // TODO: handle exception e.printStackTrace(); }finally{ //不管是否发生异常,该代码块都执行 lock.unlock(); } } } class MyThreadA extends Thread { private MyService service; public MyThreadA(MyService service) { this.service = service; } @Override public void run() { super.run(); service.MethodA(); } } class MyThreadAA extends Thread { private MyService service; public MyThreadAA(MyService service) { this.service = service; } @Override public void run() { super.run(); service.MethodA(); } } class MyThreadB extends Thread { private MyService service; public MyThreadB(MyService service) { this.service = service; } @Override public void run() { super.run(); service.MethodB(); } } class MyThreadBB extends Thread { private MyService service; public MyThreadBB(MyService service) { this.service = service; } @Override public void run() { super.run(); service.MethodB(); } }
methodA begin ThreadName=A time=1603976169500 methodA end ThreadName=A time=1603976174512 methodA begin ThreadName=AA time=1603976174512 methodA end ThreadName=AA time=1603976179521 methodB begin ThreadName=B time=1603976179521 methodB end ThreadName=B time=1603976184522 methodB begin ThreadName=BB time=1603976184522 methodB end ThreadName=BB time=1603976189534
此实验说明,调用lock.lock()代码的线程就持有了“对象监视器”,其他线程只有等待锁被释放时再次争抢。
4.1.3 使用Condition实现等待/通知
类ReentrantLock也可以实现等待/通知模式,需要借助Condition对象。在一个Lock对象里可以创建多个Condition(即对象监视器)实例,线程对象可以注册在指定的Condition中,从而可以有选择地进行线程通知,在调度线程上更加灵活。对比notify/notifyAll方法,被通知的线程却是由JVM随机选择的。
/* * lock.lock() 代码的线程持有了“对象监视器”,其他线程只有等待锁被释放时再次争抢 */ package ReentrantLock; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class t1 { public static void main(String[] args) throws InterruptedException { MyService service = new MyService(); MyThread a1 = new MyThread(service); a1.start(); Thread.sleep(3000); service.signal(); } } class MyService { private ReentrantLock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public void await() { try { lock.lock(); System.out.println("waitMethod时间为 " + System.currentTimeMillis()); condition.await(); }catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); System.out.println("锁释放了!"); } } public void signal() { try { lock.lock(); System.out.println("signal时间为" + System.currentTimeMillis()); condition.signal(); }catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); System.out.println("我已经唤醒了await()方法,我也该结束了"); } } } class MyThread extends Thread { private MyService service; public MyThread(MyService service) { this.service = service; } @Override public void run() { super.run(); service.await(); } }
waitMethod时间为 1603978989457 signal时间为1603978992471 我已经唤醒了await()方法,我也该结束了 锁释放了!
Object类中的wait()相当于Condition类中的await()方法。
Object类中的notify()相当于Condition类中的signal()方法。
/* * lock.lock() 代码的线程持有了“对象监视器”,其他线程只有等待锁被释放时再次争抢 */ package ReentrantLock; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class t1 { public static void main(String[] args) throws InterruptedException { MyService service = new MyService(); MyThreadA a = new MyThreadA(service); a.setName("A"); a.start(); MyThreadB b = new MyThreadB(service); b.setName("B"); b.start(); Thread.sleep(3000); //service.signalAll_A(); service.signalAll_B(); } } class MyService { private Lock lock = new ReentrantLock(); public Condition conditionA = lock.newCondition(); public Condition conditionB = lock.newCondition(); public void awaitA() { try { lock.lock(); System.out.println("begin awaitA时间为 " + System.currentTimeMillis() + " ThreadName = " + Thread.currentThread().getName()); conditionA.await(); //Thread.sleep(1000); System.out.println(" end awaitA时间为 " + System.currentTimeMillis() + " ThreadName = " + Thread.currentThread().getName()); }catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } public void awaitB() { try { lock.lock(); System.out.println("begin awaitB时间为 " + System.currentTimeMillis() + " ThreadName = " + Thread.currentThread().getName()); conditionB.await(); //Thread.sleep(1000); System.out.println(" end awaitB时间为 " + System.currentTimeMillis() + " ThreadName = " + Thread.currentThread().getName()); }catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } public void signalAll_A() { try { lock.lock(); System.out.println(" signalAll_A时间为 " + System.currentTimeMillis() +" ThreadName=" + Thread.currentThread().getName()); conditionA.signalAll(); }catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } public void signalAll_B() { try { lock.lock(); System.out.println(" signalAll_B时间为 " + System.currentTimeMillis() +" ThreadName=" + Thread.currentThread().getName()); conditionB.signalAll(); }catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } } class MyThreadA extends Thread { private MyService service; public MyThreadA(MyService service) { this.service = service; } @Override public void run() { super.run(); service.awaitA(); } } class MyThreadB extends Thread { private MyService service; public MyThreadB(MyService service) { this.service = service; } @Override public void run() { super.run(); service.awaitB(); } }
begin awaitA时间为 1603982264116 ThreadName = A begin awaitB时间为 1603982264116 ThreadName = B signalAll_B时间为 1603982267131 ThreadName=main end awaitB时间为 1603982267131 ThreadName = B
使用ReentrantLock对象可以唤醒指定种类的线程,可以控制部分线程。
以上是关于Lock的使用的主要内容,如果未能解决你的问题,请参考以下文章