一、什么是锁
在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行),其他线程在读取数据的时候上读锁后互不影响。这样可以提高读取效率。