两种互斥锁定机制:
1、同步
2、ReentrantLock
ReentrantLock是jdk5的新功能,通过采用ReentrantLock可以完全替换同步的传统锁定机制。 此外,ReentrantLock还可以提高面向对象和灵活性。 网上有很多文章比较两者的锁定方式,但这里很少谈论。 各位百度,谷歌这个博客也提到了这两种锁定方式实现的经典范例《生产者消费者》。
关于读写锁定,与其用语言解释,不如直接用代码解释。 以下用两个例子说明读写锁定和读写锁定的使用。
示例1 :
import java.util.HashMap;
import java.util.Map;
import Java.util.concurrent.locks.read write lock;
import Java.util.concurrent.locks.reentrantreadwritelock;
//*
* @author聪明的店员2012
*
*读写锁定:读写锁定
*
*在多线程环境中读写相同的数据时,会出现线程安全问题。 例如,当一个线程读取数据时,另一个线程
通过写入数据,导致前后数据不一致的某个线程写入数据时,也写入其他线程,同样地,成为在线程前后可见的数据的
*不一致。
*
此时,可以在读写方法中加入互斥锁。 一次只允许读取或写入一个线程,不允许其他线程的读取或写入操作。 这是
*虽然可以解决这些问题,但效率大幅下降。 因为在实际的业务场景中,用一个数据读取数据的操作次数很多
*写入数据的操作,但线程和线程之间的读取操作与线程安全无关。 如果处于读-写、写-写期间,则无需打开排他锁定
*之间锁上就行了。
*
*在这种情况下,读写锁定是最好的解决方案。
*
读/写锁定机制:
*“读-读”并不排他
*“读写”互斥
*“写-写”互斥
*
也就是说,需要随时保证。
*正在写入的线程只有一个;
*线程正在读取时,写入操作等待;
*如果线程正在写入,其他线程的写入和读取将等待。
*
*以下为缓存类: 用于指示读/写锁定的操作。 重新输入,降级
*/
公共类缓存数据{
//缓存应该都是单用户的,但在这里,我们将以单实例模式进行设计:
privatestaticcacheddatacheddata=newcacheddata (;
私密性readwritelocklock=newreentrantreadwritelock (; //读写锁定
private Map cache=new HashMap (; //缓存
私有缓存数据(
}
publicstaticcacheddatagetinstance (
返回高速数据;
}
//读缓存:
公共对象密钥{
锁定. read lock ().lock );
对象obj=null;
try {
obj=cache.get(key;
if(obj==null ) {
lock.readLock ().unlock );
//在此期间,其他线程可能会获取锁定
lock.writeLock ().lock );
try {
if(obj==null ) {
obj='查找数据库'; //实际的动作是查找数据库
//将数据更新到缓存:
cache.put(key,obj );
}
} finally {
//当前线程可以在获取写入锁定的同时获取读取锁定。 这称为锁的重载,然后导致写锁的降级,称为降级锁。
要允许重新读取到reader,请使用重新读取降级写入锁定,但当前线程维护的所有写入锁定必须已释放
//它们。 所以,在重新进入的过程中,其他线程没有机会获得锁定。 想想看。 首先解除写入锁定,在
//上读锁定,这样做有什么弊端? -这样,在解除写入锁定和获取读取锁定之前,其他线程可能会中断。
//——3354重新装入降级锁的步骤:获取写锁定,然后获取读锁定,最后
释放写入锁(重点)lock.readLock().lock();
lock.writeLock().unlock();
}
}
} finally {
lock.readLock().unlock();
}
return obj;
}
}
例子2:
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.xml.crypto.Data;
/**
* @author 聪明的店员2012
*
* jdk文档中关于ReentrantReadWriteLock类使用的一个很好的例子,以下是具体的介绍:
*
* 在使用某些种类的 Collection 时,可以使用 ReentrantReadWriteLock 来提高并发性。通常,在预期 collection
* 很大,读取者线程访问它的次数多于写入者线程,并且 entail 操作的开销高于同步开销时,这很值得一试。例如,以下
* 是一个使用 TreeMap 的类,预期它很大,并且能被同时访问。
*/
public class RWDictionary {
private final Map map = new TreeMap();
private final ReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock readLock = rwl.readLock();
private final Lock writeLock = rwl.writeLock();
public Data get(String key) {
readLock.lock();
try {
return map.get(key);
} finally {
readLock.unlock();
}
}
public String[] allKeys() {
readLock.lock();
try {
return (String[]) map.keySet().toArray();
} finally {
readLock.unlock();
}
}
public Data put(String key, Data value) {
writeLock.lock();
try {
return map.put(key, value);
} finally {
writeLock.unlock();
}
}
public void clear() {
writeLock.lock();
try {
map.clear();
} finally {
writeLock.unlock();
}
}
}