Condition结构提供了基本方法如下:
void await() throws InterruptedException;
void awaitUninterruptibly();
long awaitNanos(long nanosTimeout) throws InterruptedException;
boolean await(long time, TimeUnit unit) throws InterruptedException;
boolean awaitUntil(Date deadline) throws InterruptedException;
void signal();
void signalAll();
  • await()方法会使当前线程等待,同时释放当前锁,当其他线程中使用singal()和signalAll()方法时,线程会重新获得锁并继续执行.或者当前线程中断时,也跳出等待.
  • awaitUninterruptibly()方法与await()方法基本相同,,但是它并不会在等待过程中中断响应.
  • singal()方法用于唤醒一个在等待的线程,
public class ReenterLockCondition implements Runnable {
public static ReentrantLock lock = new ReentrantLock();
public static Condition condition = lock.newCondition(); /**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see Thread#run()
*/
@Override
public void run() {
try {
lock.lock();
condition.await();
System.out.println("Thread is going on");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public static void main(String[] args) throws InterruptedException {
ReenterLockCondition r1 = new ReenterLockCondition();
Thread t1 = new Thread(r1);
t1.start();
Thread.sleep(2000);
lock.lock();
condition.signal();
lock.unlock();
}
}
     当线程使用Condition.await()时,要求线程持有相关的重入锁,在Condition.await()调用后,这个线程会释放这把锁,同理 在Condition.signal()方法调用时,也要求线程先获得相关的锁,在signal()方法调用后,西永会从当前的Condition对象的等待队列中,唤醒一个线程,.一旦线程被唤醒,他会重新尝试获得与之绑定的重入锁,一旦成功获取,就可以继续执行,因此,在signal()方法调用后,一般需要释放相关的锁.
     put()的实现如下:
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
// Note: convention in all put/take/etc is to preset local var
// holding count negative to indicate failure unless set.
int c = -1;
Node<E> node = new Node<E>(e);
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
putLock.lockInterruptibly();//可以响应中断的锁 加锁
try {
/*
* Note that count is used in wait guard even though it is
* not protected by lock. This works because count can
* only decrease at this point (all other puts are shut
* out by lock), and we (or some other waiting put) are
* signalled if it ever changes from capacity. Similarly
* for all other uses of count in other wait guards.
*/
while (count.get() == capacity) {//判断队列是否满了
notFull.await();//等待
}
enqueue(node);//插入数据
c = count.getAndIncrement();//更新总数,变量c是count加1前的值
if (c + 1 < capacity)
notFull.signal();//有足够的空间,通知其他线程
} finally {
putLock.unlock();//释放锁
}
if (c == 0)
signalNotEmpty();//插入成功后,通知take操作去数据
}
     通过takeLock和putLock两把锁,LinkedBlockingQueue实现了取数据和写数据的分离,使两者在真正意义上成为可以并发的操作
  • 锁粗化,在开发过程中,应该有意识地在合理的场合进行锁的粗化,尤其在循环内请求锁时,如果对一个锁不停地进行请求,同步和释放,其本身也会消耗宝贵的资源,反而不利于性能的优化,
性能的优化是根据运行时的真实情况对各个资源点进行权衡折中的过程,锁粗化的思想和减少锁的持有时间是相反的,但在不同的场合,他们的效果并不相同.所有大家需要根据实际情况,进行权衡.

重入锁的好搭档:Condition条件(读书笔记)的更多相关文章

  1. 深入理解java:2.3.2. 并发编程concurrent包 之重入锁/读写锁/条件锁

    重入锁 Java中的重入锁(即ReentrantLock)   与JVM内置锁(即synchronized)一样,是一种排它锁. ReentrantLock提供了多样化的同步,比如有时间限制的同步(定 ...

  2. Java并发编程笔记1-竞争条件&初识原子类&可重入锁

    我们知道,在多线程访问一个共享变量的时候会发生安全问题. 首先看下面例子: public class Counter { private int count; public void add(){ t ...

  3. java ReentrantLock可重入锁功能

    1.可重入锁是可以中断的,如果发生了死锁,可以中断程序 //如下程序出现死锁,不去kill jvm无法解决死锁 public class Uninterruptible { public static ...

  4. synchronized关键字,Lock接口以及可重入锁ReentrantLock

    多线程环境下,必须考虑线程同步的问题,这是因为多个线程同时访问变量或者资源时会有线程争用,比如A线程读取了一个变量,B线程也读取了这个变量,然后他们同时对这个变量做了修改,写回到内存中,由于是同时做修 ...

  5. Java中可重入锁ReentrantLock原理剖析

    本文由码农网 – 吴极心原创,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! 一. 概述 本文首先介绍Lock接口.ReentrantLock的类层次结构以及锁功能模板类AbstractQue ...

  6. ReenTrantLock可重入锁(和synchronized的区别)总结

    ReenTrantLock可重入锁(和synchronized的区别)总结 可重入性: 从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也 ...

  7. j.u.c系列(05)---之重入锁:ReentrantLock

    写在前面 ReentrantLock,可重入锁,是一种递归无阻塞的同步机制.它可以等同于synchronized的使用,但是ReentrantLock提供了比synchronized更强大.灵活的锁机 ...

  8. Java并发编程原理与实战十七:AQS实现重入锁

    一.什么是重入锁 可重入锁就是当前持有锁的线程能够多次获取该锁,无需等待 二.什么是AQS AQS是JDK1.5提供的一个基于FIFO等待队列实现的一个用于实现同步器的基础框架,这个基础框架的重要性可 ...

  9. 从源码角度彻底理解ReentrantLock(重入锁)

    目录 1.前言 2.AbstractQueuedSynchronizer介绍 2.1 AQS是构建同步组件的基础 2.2 AQS的内部结构(ReentrantLock的语境下) 3 非公平模式加锁流程 ...

随机推荐

  1. 几个简单的VBS脚本程序以及其JS实现

    1 语音发声脚本,调用sapi.spvoice读英语hh  保存为say.vbs,点击打开就可以念诗: set objTTS = CreateObject("sapi.spvoice&quo ...

  2. bzoj3643 Phi的反函数

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3643 [题解] n = p1^a1*p2^a2*...*pm^am phi(n) = p1( ...

  3. 强引用(StrongReference)、弱引用(WeakReference)、软引用(SoftReference)、虚引用(PhantomReference)

    1.强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.如下: Object o=new Object(); // 强引用 当内存空间 ...

  4. Java并发笔记(一)

    1. lock (todo) 2. 写时复制容器 CopyOnWrite容器即写时复制的容器.通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个 ...

  5. JSP中include指令和include动作浅析

    一. JSP工作原理 JSP文件是一种Servlet,其工作方式是先部署源代码后编译为.class文件.JSP会在客户端第一次请求JSP文件时被编译成Servlet,由Servlet处理客户端的请求. ...

  6. http请求分析

    一个Http请求一般始于如下几种方式: 1.在浏览器中输入一个URL地址 2.网页中的一个超链接 3.Response.Redirect("http://www.sohu.com" ...

  7. centos编译安装vim并支持lua

    系统环境:centos6.5 x86 (basic server) 1.安装编译环境. # yum groupinstall "Development Tools" 2.安装vim ...

  8. Android 中带有进度条效果的按钮(Button)

    安卓中带有进度条效果的按钮,如下图: 1.布局文件如下activity_main.xml <RelativeLayout xmlns:android="http://schemas.a ...

  9. J.U.C并发框架源码阅读(七)CyclicBarrier

    基于版本jdk1.7.0_80 java.util.concurrent.CyclicBarrier 代码如下 /* * ORACLE PROPRIETARY/CONFIDENTIAL. Use is ...

  10. (29)C#多线程

    使用线程的原因 1.不希望用户界面停止响应. 2.所有需要等待的操作,如文件.数据库或网络访问需要一定的时间. 一个进程的多个线程可以同时运行不同cpu或多核cpu的不同内核上 注意多线程访问相同的数 ...