Lock 实现提供了比使用 synchronized 方法和语句可得到的更普遍的锁定操做。此实现容许更灵活的结构,能够具备差异很大的属性,能够支持多个相关的 Condition 对象。 锁是控制多个线程对共享资源进行访问的工具。一般,锁提供了对共享资源的独占访问。一次只能有一个线程得到锁,对共享资源的全部访问都须要首先得到锁。不过,某些锁可能容许对共享资源并发访问,如 ReadWriteLock 的读取锁。 synchronized 方法或语句的使用提供了对与每一个对象相关的隐式监视器锁的访问,但却强制全部锁获取和释放均要出如今一个块结构中:当获取了多个锁时,它们必须以相反的顺序释放,且必须在与全部锁被获取时相同的词法范围内释放全部锁。 虽然 synchronized 方法和语句的范围机制使得使用监视器锁编程方便了不少,并且还帮助避免了不少涉及到锁的常见编程错误,但有时也须要以更为灵活的方式使用锁。例如,某些遍历并发访问的数据结果的算法要求使用 "hand-over-hand" 或 "chain locking":获取节点 A 的锁,而后再获取节点 B 的锁,而后释放 A 并获取 C,而后释放 B 并获取 D,依此类推。Lock 接口的实现容许锁在不一样的做用范围内获取和释放,并容许以任何顺序获取和释放多个锁,从而支持使用这种技术。 Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成大相径庭的对象,以便经过将这些对象与任意 Lock 实现组合使用,为每一个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。 条件(也称为条件队列 或条件变量)为线程提供了一个含义,以便在某个状态条件如今可能为 true 的另外一个线程通知它以前,一直挂起该线程(即让其“等待”)。由于访问此共享状态信息发生在不一样的线程中,因此它必须受保护,所以要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是:以原子方式 释放相关的锁,并挂起当前线程,就像 Object.wait 作的那样。 Condition 实例实质上被绑定到一个锁上。要为特定 Lock 实例得到 Condition 实例,请使用其 newCondition() 方法。 主要相同点:Lock能完成Synchronized所实现的全部功能。 主要不一样点:Lock有比Synchronized更精确的县城予以和更好的性能。Synchronized会自动释放锁,可是Lock必定要求程序员手工释放,而且必须在finally从句中释放。 synchronized 修饰方法时 表示同一个对象在不一样的线程中 表现为同步队列 若是实例化不一样的对象 那么synchronized就不会出现同步效果了。 1.对象的锁 全部对象都自动含有单一的锁。 JVM负责跟踪对象被加锁的次数。若是一个对象被解锁,其计数变为0。在任务(线程)第一次给对象加锁的时候,计数变为1。每当这个相同的任务(线程)在此对象上得到锁时,计数会递增。 只有首先得到锁的任务(线程)才能继续获取该对象上的多个锁。 每当任务离开一个synchronized方法,计数递减,当计数为0的时候,锁被彻底释放,此时别的任务就可使用此资源。 2.synchronized同步块 2.1同步到单一对象锁 当使用同步块时,若是方法下的同步块都同步到一个对象上的锁,则全部的任务(线程)只能互斥的进入这些同步块。 Resource1.java演示了三个线程(包括main线程)试图进入某个类的三个不一样的方法的同步块中,虽然这些同步块处在不一样的方法中,但因为是同步到同一个对象(当前对象 synchronized (this)),因此对它们的方法依然是互斥的。 package com.org.thread; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** *@DEMO:JavaSE *@Author:jilongliang *@Date:2013-3-21 */ public class Locker { public static void main(String[] args) { Resources1 res = new Resources1(); Pro p = new Pro(res); Customer1 c = new Customer1(res); new Thread(p).start(); new Thread(c).start(); } } class Pro implements Runnable { Resources1 resource; Pro(Resources1 res) { this.resource = res; } @Override public void run() { while (true) { try { resource.set("商品"); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Customer1 implements Runnable { Resources1 res; Customer1(Resources1 res) { this.res = res; } @Override public void run() { while (true) { synchronized (res) { try { res.out(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } /** * wait notify notifyAll 都在使用在同步中,由于要对持有监视器(锁)的线程 操做 因此要使用在同步中,由于只有同步才具备锁 * 为何这些操做线程的方法要定义Object类中? * 由于这些方法在操做同步中线程时,都必需要标识他们所操做线程只有的锁 * 只有同一个锁上的被等待线程,能够被同一个锁上的notify唤醒 不能够对不一样锁中的线程进行唤醒 * 也就是说,等待和唤醒必须是同一个锁 而锁能够是任意对象,因此能够被任意对象调用的方法定义了 * Object类中 */ class Resources1 { private String name; private int count = 1; private boolean flag = false; private Lock lock = new ReentrantLock(); private Condition condition_pro = lock.newCondition(); private Condition condition_con = lock.newCondition(); public void set(String name) throws InterruptedException { lock.lock(); try { while (flag) // this.wait(); condition_pro.await();// 等待 this.name = name + "=生产数:" + count++; System.out.println(Thread.currentThread().getName() + "生产者:" + this.name); flag = true; condition_con.signalAll(); // this.notifyAll(); } finally { lock.unlock(); } } public void out() throws InterruptedException { lock.lock(); try { while (!flag) // this.wait(); condition_con.await(); System.out.println(Thread.currentThread().getName() + "消费者===========" + this.name); flag = false; condition_pro.signalAll(); // this.notifyAll(); } finally { lock.unlock(); } } }