读写锁
相比Java中的锁(Locks in Java)里Lock实现,读写锁更复杂一些。假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写(译者注:也就是说:读-读能共存,读-写不能共存,写-写不能共存)。这就需要一个读/写锁来解决这个问题。Java5在java.util.concurrent包中已经包含了读写锁。尽管如此,我们还是应该了解其实现背后的原理。
读 写 这种的 可以用wait notify 之前已经实现过了 读的时候不能写 写的时候不能做 保证共性的全局变量安全
下面,先来写个读写锁大家看看:
package com.toov5.readAndWriteLock;
import java.util.HashMap;
import java.util.Map;
//读写锁 类似jvm内置缓存(把值存到jvm中)
public class writeAndReadLock {
private volatile Map<Object,Object> cache = new HashMap<>();
//写入元素
public void put(String key,String value){
try {
Thread.sleep(500);
System.out.println("写入"+key+value);
cache.put(key, value);
System.out.println("写入"+key+value+"结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//读取元素
public String get(String key){
try {
Thread.sleep(500);
System.out.println("读取"+key);
String result = cache.get(key).toString();
System.out.println("读取"+key+"结束");
return result;
} catch (Exception e) {
return null;
}
}
public static void main(String[] args) {
writeAndReadLock lock = new writeAndReadLock();
//写线程
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for(int i =0; i<10;i++){
lock.put("i", i+"");
}
}
});
//读线程
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i<10;i++){
lock.get(i+"");
}
}
});
t1.start();
t2.start();
}
}
结果:
如果两个方法都加上synchronize 那么读的时候 不能写 写的时候不能读
下面提供读写锁:
package com.toov5.readAndWriteLock;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
//读写锁 类似jvm内置缓存(把值存到jvm中)
public class writeAndReadLock {
private volatile Map<Object,Object> cache = new HashMap<>();
private ReentrantReadWriteLock wrl = new ReentrantReadWriteLock();
private WriteLock wirtelock=wrl.writeLock();//获取到写锁
private ReadLock readLock =wrl.readLock(); //获取到读锁
//写入元素
public void put(String key,String value){
try {
wirtelock.lock();
Thread.sleep(500);
System.out.println("写入"+key+value);
cache.put(key, value);
System.out.println("写入"+key+value+"结束");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
wirtelock.unlock();
}
}
//读取元素
public String get(String key){
try {
readLock.lock();
Thread.sleep(500);
System.out.println("读取"+key);
String result = cache.get(key).toString();
System.out.println("读取"+key+"结束");
return result;
} catch (Exception e) {
return null;
}finally{
readLock.unlock();
}
}
public static void main(String[] args) {
writeAndReadLock lock = new writeAndReadLock();
//写线程
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for(int i =0; i<10;i++){
lock.put("i", i+"");
}
}
});
//读线程
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i<10;i++){
lock.get(i+"");
}
}
});
t1.start();
t2.start();
}
}
没有写完时候 是不能读的
看源码:
与之前的lock锁不一样之前是 reentrantlock,它有读和写两把锁
两个线程同时写,同时读是不可能的。不共存!
读读 可以 读写不可共存 写写不可以共存