一、什么是锁
在Java的util.concurrent.locks包下有关于锁的接口和类如下:
先看一段代码:
package com.codeing.snail.test; public class ReadWriteLockTest { public static void main(String[] args) { final Output output = new Output(); new Thread(){ public void run() { while(true){ output.output("CodeingSnail"); } }; }.start(); new Thread(){ public void run() { while(true){ output.output("阳光小强"); } }; }.start(); } static class Output{ public void output(String name){ char[] arry = name.toCharArray(); for(int i = 0; i < arry.length; i++){ System.out.print(arry[i]); } System.out.println(); } } }
输出的结果如下:
如果我们想让“CodeingSnail"和“阳光小强"两个字符串都能完整输出,就需要使用synchronized关键字将输出部分声明,如下:
public synchronized void output(String name){ char[] arry = name.toCharArray(); for(int i = 0; i < arry.length; i++){ System.out.print(arry[i]); } System.out.println(); }
其实,除了synchronized关键字之外,还可以使用锁(Lock)来实现同步。
ReentrantLock lock = new ReentrantLock(); public void output(String name){ lock.lock(); try{ char[] arry = name.toCharArray(); for(int i = 0; i < arry.length; i++){ System.out.print(arry[i]); } System.out.println(); }finally{ lock.unlock(); } }上面代码使用try...finally语句块是为了防止出现异常执行不到unlock方法,ReentrantLock是Lock的实现类,Lock的作用和synchronized类似,但更加面向对象,要实现同步就必须使用同一个lock对象。
二、什么是读写锁
读写锁、分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥。下面我们来看一下API文档中的一个缓存器的例子:
class CachedData { Object data; volatile boolean cacheValid; final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); void processCachedData() { rwl.readLock().lock(); if (!cacheValid) { // Must release read lock before acquiring write lock rwl.readLock().unlock(); rwl.writeLock().lock(); try { // Recheck state because another thread might have // acquired write lock and changed state before we did. if (!cacheValid) { data = ... cacheValid = true; } // Downgrade by acquiring read lock before releasing write lock rwl.readLock().lock(); } finally { rwl.writeLock().unlock(); // Unlock write, still hold read } } try { use(data); } finally { rwl.readLock().unlock(); } } }假如有多个线程来读取数据,第一个线程进来先上一把写锁进行数据写入(先释放读锁),写入完成后将写锁降级为读锁(第15行),其他线程在读取数据的时候上读锁后互不影响。这样可以提高读取效率。