Lock myLock = new ReentrantLock(); myLock.lock();//获取锁 try{ //do something }finally{ //释放锁。须要放在finally子句内,不然抛异常后,锁未被释放,其余线程则会永远被阻塞 myLock.unlock(); }
读写锁分为读锁和写锁。多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥。 java
Java中读写锁有个接口java.util.concurrent.locks.ReadWriteLock,也有具体的实现ReentrantReadWriteLock。 数据库
在实际开发中,最好在能用读写锁的状况下使用读写锁,而不要用普通锁,以求更好的性能。 缓存
public class SimpleCacheDemo{ private Map<String, Object> cache = new HashMap<String, Object>(); private ReadWriteLock rwlock = new ReentrantReadWriteLock(); public Object getData(String key){ rwlock.readLock().lock(); Object obj = null; try{ obj = cache.get(key); if(obj == null){ rwlock.readLock().unlock(); rolock.wirteLock().lock(); try{ if(obj == null){ obj = queryDB(key); if(obj != null){ cache.put(key, obj); return obj; } } }finally{ rwlock.writeLock().unlock(); } rwlock.readLock().lock(); } }finally{ rwlock.readLock().unlock(); } return obj; } //从数据库查出值 public Object queryDB(key){ //todo return null; } }
条件变量都实现了java.util.concurrent.locks.Condition接口,条件变量的实例化是经过一个Lock对象上调用newCondition()方法来获取的,这样,条件就和一个锁对象绑定起来了。所以,Java中的条件变量只能和锁配合使用,来控制并发程序访问竞争资源的安全。 安全
条件变量的出现是为了更精细控制线程等待与唤醒,在Java5以前,线程的等待与唤醒依靠的是Object对象的wait()和notify()/notifyAll()方法,这样的处理不够精细。 并发
Condition将Object监视器方法wait()、notify()、notifyAll()分解成大相径庭的对象,以便经过这些对象与任意Lock实现组合使用。 对应的方法是:await()、signal() 、signalAll() 。import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * Java线程:并发协做-生产者消费者模型 */ public class ProducerConsumer { public static void main(String[] args) { Godown godown = new Godown(30); Consumer c1 = new Consumer(50, godown); Consumer c2 = new Consumer(20, godown); Consumer c3 = new Consumer(30, godown); Producer p1 = new Producer(10, godown); Producer p2 = new Producer(10, godown); Producer p3 = new Producer(50, godown); Producer p4 = new Producer(10, godown); Producer p5 = new Producer(70, godown); c1.start(); c2.start(); c3.start(); p1.start(); p2.start(); p3.start(); p4.start(); p5.start(); } } /** * 仓库 */ class Godown { public static final int max_size = 100; //最大库存量 public int curnum; //当前库存量 private final Lock lock = new ReentrantLock(); private final Condition connProduce = lock.newCondition(); private final Condition connConsume = lock.newCondition(); public Godown() { } public Godown(int curnum) { this.curnum = curnum; } /** * 生产指定数量的产品 * * @param neednum */ public void produce(int neednum) { lock.lock(); try{ //测试是否须要生产 while (neednum + curnum > max_size) { System.out.println("要生产的产品数量" + neednum + "超过剩余库存量" + (max_size - curnum) + ",暂时不能执行生产任务!"); try { //当前的生产线程等待 connProduce.await(); } catch (InterruptedException e) { e.printStackTrace(); } } //知足生产条件,则进行生产,这里简单的更改当前库存量 curnum += neednum; System.out.println("已经生产了" + neednum + "个产品,现仓储量为" + curnum); //唤醒在此对象监视器上等待的全部消费线程 connConsume.signalAll(); }finally{ lock.unlock(); } } /** * 消费指定数量的产品 * * @param neednum */ public void consume(int neednum) { lock.lock(); try{ //测试是否可消费 while (curnum < neednum) { try { //当前的消费线程等待 connConsume.await(); } catch (InterruptedException e) { e.printStackTrace(); } } //知足消费条件,则进行消费,这里简单的更改当前库存量 curnum -= neednum; System.out.println("已经消费了" + neednum + "个产品,现仓储量为" + curnum); //唤醒在此对象监视器上等待的全部生产线程 connProduce.signalAll(); }finally{ lock.unlock(); } } } /** * 生产者 */ class Producer extends Thread { private int neednum; //生产产品的数量 private Godown godown; //仓库 Producer(int neednum, Godown godown) { this.neednum = neednum; this.godown = godown; } public void run() { //生产指定数量的产品 godown.produce(neednum); } } /** * 消费者 */ class Consumer extends Thread { private int neednum; //生产产品的数量 private Godown godown; //仓库 Consumer(int neednum, Godown godown) { this.neednum = neednum; this.godown = godown; } public void run() { //消费指定数量的产品 godown.consume(neednum); } }