频道栏目
IT货架 > > 正文
《Java并发编程从入门到精通》显示锁Lock和ReentrantLock
网友分享于:Jan 1, 1970 8:00:00 AM    来源: IT货架   
作者:张振华    购买链接:天猫商城  JD商城  当当书店   显示锁Lock和ReentrantLock Lock是一个接口提供了无条件的、可轮询的、定时的、可中断的锁获取操作,所有加锁和解锁的方法都是显式的。包路径是:java.util.concurrent.locks.Lock。核心方法是lock(),unlock(),tryLock(),实现类有ReentrantLock, ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock。 看一下Lock接口有如下方法: public abstract interface Lock { public abstract void lock(); public abstract void lockInterruptibly() throws InterruptedException; public abstract boolean tryLock(); public abstract boolean tryLock(long paramLong , TimeUnit paramTimeUnit) throws InterruptedException; public abstract void unlock(); public abstract Condition newCondition(); } 对应的解说如下: void lock();获取锁。如果锁不可用,出于线程调度目的,将禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态。 void lockInterruptibly() throws InterruptedException;如果当前线程未被中断,则获取锁。如果锁可用,则获取锁,并立即返回。如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下两种情况之一以前,该线程将一直处于休眠状态:锁由当前线程获得;或者其他某个线程中断 当前线程,并且支持对锁获取的中断。如果当前线程:在进入此方法时已经设置了该线程的中断状态;或者在获取锁时被中断 ,并且支持对锁获取的中断,则将抛出  InterruptedException ,并清除当前线程的已中断状态。 boolean tryLock();仅在调用时锁为空闲状态才获取该锁。如果锁可用,则获取锁,并立即返回值  true 。如果锁不可用,则此方法将立即返回值  false 。通常对于那些不是必须获取锁的操作可能有用。 boolean tryLock(long time, TimeUnit unit) throws InterruptedException;如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。如果锁可用,则此方法将立即返回值  true 。如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下三种情况之一前,该线程将一直处于休眠状态: void unlock();释放锁。对应于lock()、tryLock()、tryLock(xx)、lockInterruptibly()等操作,如果成功的话应该对应着一个unlock(),这样可以避免死锁或者资源浪费。 newCondition() 返回用来与此 Lock 实例一起使用的 Condition 实例。 ReentrantLock是Lock的实现类,是一个互斥的同步器,它具有扩展的能力。在竞争条件下,ReentrantLock 的实现要比现在的 synchronized 实现更具有可伸缩性。(有可能在 JVM 的将来版本中改进 synchronized 的竞争性能)这意味着当许多线程都竞争相同锁定时,使用 ReentrantLock 的吞吐量通常要比 synchronized 好。换句话说,当许多线程试图访问 ReentrantLock 保护的共享资源时,JVM 将花费较少的时间来调度线程,而用更多个时间执行线程。虽然 ReentrantLock 类有许多优点,但是与同步相比,它有一个主要缺点 — 它可能忘记释放锁定。ReentrantLock实在工作中对方法块加锁使用频率最高的。 使用方法如下: class X { private final ReentrantLock lock = new ReentrantLock(); // … public void m() { lock.lock(); // 获得锁 try { // … 方法体 } finally { lock.unlock();//解锁 } } } Lock与synchronized 的比较: 1:Lock使用起来比较灵活,但是必须有释放锁的动作; 2:Lock必须手动释放和开启锁,synchronized 不需要; 3:Lock只适用与代码块锁,而synchronized 对象之间的互斥关系; 请注意以下两种方式的区别: 第一种方式:两个方法之间的锁是独立的。如下: public class ReentrantLockDemo { public static void main(String[] args) { final Count ct = new Count(); for (int i = 0; i < 2; i++) { new Thread() { @Override public void run() { ct.get(); } }.start(); }   for (int i = 0; i < 2; i++) { new Thread() { @Override public void run() { ct.put(); } }.start(); } } } class Count { public void get() { final ReentrantLock lock = new ReentrantLock(); try { lock.lock(); // 加锁 System. out.println(Thread.currentThread().getName() + “get begin”); Thread. sleep(1000L);// 模仿干活 System. out.println(Thread.currentThread().getName() + “get end”); lock.unlock(); // 解锁 } catch (InterruptedException e) { e.printStackTrace(); } } public void put() { final ReentrantLock lock = new ReentrantLock(); try { lock.lock(); // 加锁 System. out.println(Thread.currentThread().getName() + “put begin”); Thread. sleep(1000L);// 模仿干活 System. out.println(Thread.currentThread().getName() + “put end”); lock.unlock(); // 解锁 } catch (InterruptedException e) { e.printStackTrace(); } } } 运行结果如下(每次运行结果都是不一样的,仔细体会一下): Thread-0get begin Thread-1get begin Thread-2put begin Thread-3put begin Thread-0get end Thread-2put end Thread-3put end Thread-1get end 第二种方式,两个方法之间使用相同的锁。 ReentrantLockDemo 类的内容不变,将Count中的ReentrantLock改成全局变量,如下所示: class Count { final ReentrantLock lock = new ReentrantLock(); public void get() { try { lock.lock(); // 加锁 System. out.println(Thread.currentThread().getName() + “get begin”); Thread. sleep(1000L);// 模仿干活 System. out.println(Thread.currentThread().getName() + “get end”); lock.unlock(); // 解锁 } catch (InterruptedException e) { e.printStackTrace(); } } public void put() { try { lock.lock(); // 加锁 System. out.println(Thread.currentThread().getName() + “put begin”); Thread. sleep(1000L);// 模仿干活 System. out.println(Thread.currentThread().getName() + “put end”); lock.unlock(); // 解锁 } catch (InterruptedException e) { e.printStackTrace(); } } } 运行结果如下(每次运行结果一样的,仔细体会一下): Thread-0get begin Thread-0get end Thread-1get begin Thread-1get end Thread-2put begin Thread-2put end Thread-3put begin Thread-3put end 原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 《Java并发编程从入门到精通》显示锁Lock和ReentrantLock About Latest Posts 张振华_jack Latest posts by 张振华_jack (see all) 《Java并发编程从入门到精通》显示锁Lock和ReentrantLock - 2015年9月19日 《 Java并发编程从入门到精通》Thread安全与不安全 - 2015年9月12日 《 Java并发编程从入门到精通》 常见的内存溢出的三种情况 - 2015年9月7日 添加本文到我的收藏 Related posts: Java锁的种类以及辨析(四):可重入锁 《 Java并发编程从入门到精通》目录和序言 《 Java并发编程从入门到精通》第5章 多线程之间交互:线程阀 《 Java并发编程从入门到精通》 Java线程池的监控 《 Java并发编程从入门到精通》 常见的内存溢出的三种情况 《 Java并发编程从入门到精通》Thread安全与不安全 ReentrantLock(重入锁)以及公平性 Oracle官方并发教程之锁对象 Java锁是如何保证数据可见性的 基本线程同步(七)修改Lock的公平性 测试并发应用 (一)监控Lock接口 Java锁的种类以及辨析(三):阻塞锁 Bug:StampedLock的中断问题导致CPU爆满 java锁的种类以及辨析(一):自旋锁 基本线程同步(五)使用Lock同步代码块

广告服务联系QQ:1134687142 | 网站地图

版权所有: IT货架- 内容来自互联网,仅供用于技术学习,请遵循相关法律法规. 京ICP备11030978号-1