欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Lock的使用

程序员文章站 2022-03-09 18:58:56
...
Lock的使用

lock也能实现同步效果,而且使用更加方便
1.ReentrantLock类的使用
2.ReentrantReadWriteLock类的使用
使用ReentrantLock类

java多线程中,使用synchronized来实现线程之间的互斥,但在jdk1.5之后增加了ReentrantLock类,也能达到同样的效果,在扩展功能上
也更加强大,如嗅探锁定,多路分支通知等,而且使用也更加灵活。
1.使用ReentrantLock实现同步:测试1
  Lock lock = new ReentrantLock();
  获取锁lock.lock();
  释放锁lock.unlock();
2.使用ReentrantLock实现同步:测试2
  lock.lock();使用的是对象监视器,其它线程只能等待锁被释放时再次争抢。
3.使用Condition实现等待/通知:错误用法与解决
  类ReentrantLock需要借助Condition对象实现wait()和notify()/notifyAll()模式
  在一个Lock当中,可以创建多个Condition实例(对象监视器),线程对象可以注册在指定的Condition中,从而可以有选择的进行线程通知,在调度线程上更加灵活

  使用notify()/notifyAll()通知线程时,被通知的线程是有jvm随机选择的,但是使用 类ReentrantLock结合Condition对象可以实现选择性通知,这个功能非常重要,
  而且Condition默认提供支持

  而synchronized相当于整个lock对象中只有一个Condition实例,所有线程都注册在它身上。线程开始notifyAll时,需要通知所有wait线程,会有效率问题

   Lock lock = new ReentrantLock();
   Condition condition = lock.newCondition
   获取锁lock.lock();  //必须要获得锁
   condition.await();
   总结:condition使线程等待必须要先获得锁
4.正确使用Condition实现等待/通知
  Object类中的wait()方法相当于Condition中的await()方法
  Object类中的wait(long)方法相当于Condition中的await(long)方法
  Object类中的notify()方法相当于Condition中的signal()方法
  Object类中的notifyAll()方法相当于Condition中的signalAll()方法
5.使用多个Condition实现通知部分线程:错误用法
  一个Condition signalAll会唤醒所有该Condition对应的await方法
6.使用多个Condition实现通知部分线程:正确用法
  一个Condition signalAll方法对应一个Condition await方法
7.实现生产者/消费者模式:一对一交替打印
  增加一个公共变量
  实际就是本线程执行完改变条件停止本线程,通知其他线程执行
8.实现生产者/消费者模式:多对多交替打印
  有可能出现假死问题,Condition需要signalAll处理
9.公平锁和非公平锁
  lock锁分为公平锁和非公平锁
  公平锁:线程获得锁的顺序必须按照线程加锁的顺序来分配的,即先来先得的锁,先进先出。
  非公平锁:是一种获取锁的抢占机制,是随机获得锁,这种有可能导致某一个线程一直拿不到锁
  注意:是线程加锁的顺序决定获得锁的顺序
        线程开始执行就是加锁获得锁就是lock.lock();
  ReentrantLock(true); true:公平锁
                       false:非公平锁
10.方法getHoldCount(),getQueueLength()和getWaitQueueLength()的测试
  getHoldCount():查询当前线程保持此锁定的个数,也就是调用次数;                   该线程lock数;
  getQueueLength():获取正等待获取此锁定的线程的估计数;                          还没有获得锁数;
  getWaitQueueLength(Condition condition):返回等待与此锁定相关的给定条件Condition的线程估计数;      获得锁之后wait数;
11.方法hasQueuedThread(),hasQueuedThreads()和hasWaiters()的测试
  hasQueuedThread(Thread thread):查询指定线程是否正在等待获取此锁定                    是否有指定线程正在等待获取此锁定
  hasQueuedThreads():查询是否有正在等待获取此锁定                                      是否有等待获取次锁定线程
  hasWaiters(Condition condition):查询是否有线程正在等待与此锁定有关的condition条件    是否有wait数
12.方法isFair(),isHeldByCurrentThread()和isLock()的测试
  isFair():是不是公平锁
  isHeldByCurrentThread():当前线程是否保持锁定
  isLock():查询此锁定是否由任意线程保持
13.方法lockInterruptibly(),tryLock()和tryLock(long timeout,TimeUnit unit)的测试。
  lockInterruptibly():如果当前线程未被中断,则获取锁定,如果已经中断,者抛出异常
  tryLock():仅在调用时锁定未被另一个线程保持的情况下获取锁
  tryLock(long timeout,TimeUnit unit);如果锁定在给定时间段内没有被另外一个线程保持,或者当前线程未被中断,则获取锁
  注:和lock.lock()一致,都是获取锁定,只是这个有条件获取
14.方法awaitUninterruptibly()的使用
  和condition.await()方法一样,暂停线程,这个暂停线程之后调用interrupt()方法不会报错
15.方法awaitUntil()的使用
  awaitUntil(Date deadline)暂停线程多久后自动唤醒,也可在时间到达之前被其它线程唤醒
16.使用Condition实现顺序执行
  和一对一交替打印类似。




使用ReentrantReadWriteLock

类ReentrantLock具有完全互斥排他的效果,即同一时间只有一个线程在执行lock后面的任务,这样保证了实例变量的安全性,但是效率非常低
jdk中提供一种读写锁ReentrantReadWriteLock类,可以加快运行效率
1.类ReentrantReadWriteLock的使用:读读共享
  private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
  reentrantReadWriteLock.readLock().lock(); 获得锁
  允许多线程同时执行lock()后面的方法
2.类ReentrantReadWriteLock的使用:写写互斥
  reentrantReadWriteLock.writeLock().lock();
  锁代码reentrantReadWriteLock.writeLock()同一时间只允许一个线程执行之后的代码
3.类ReentrantReadWriteLock的使用:读写互斥
4.类ReentrantReadWriteLock的使用:写读互斥
  结论:只要操作中有写操作都是互斥的

 

相关标签: lock