接口关系
(1)Lock和ReadWriteLock是两大锁的根接口,Lock代表实现类是ReentrantLock(可重入锁),ReadWriteLock(读写锁)的代表实现类是ReentrantReadWriteLock。
Lock 接口支持那些语义不同(重入、公平等)的锁规则,可以在非阻塞式结构的上下文(包括 hand-over-hand 和锁重排算法)中使用这些规则。主要的实现是 ReentrantLock。
ReadWriteLock 接口以类似方式定义了一些读取者可以共享而写入者独占的锁。此包只提供了一个实现,即 ReentrantReadWriteLock,因为它适用于大部分的标准用法上下文。但程序员可以创建自己的、适用于非标准要求的实现。
(2)Condition 接口描述了可能会与锁有关联的条件变量。这些变量在用法上与使用 Object.wait 访问的隐式监视器类似,但提供了更强大的功能。需要特别指出的是,单个 Lock 可能与多个 Condition 对象关联。为了避免兼容性问题,Condition 方法的名称与对应的 Object 版本中的不同。
可重入锁
可重入就是说某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。
代码示例:
package threadcontrol;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockDemo {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
for (int i = 0; i < 10; i++) {
lock.lock();
System.out.println("加锁"+i);
}
for (int i = 0; i < 10; i++) {
try {
System.out.println("解锁:"+i);
}finally {
lock.unlock();
}
}
}
}
运行结果:
读写锁
读写锁实际是一种特殊的自旋锁,它把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。
代码示例:
package threadcontrol;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteDemo {
private Map<String,String>map = new HashMap<>();
ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();
ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();
public String get(String key){
try {
readLock.lock();
System.out.println(Thread.currentThread().getName()+" 已加锁,开始读操作");
Thread.sleep(1000);
return map.get(key);
}catch (Exception e){
e.printStackTrace();
return null;
}finally {
readLock.unlock();
}
}
public void set(String key,String value){
try {
readLock.lock();
System.out.println(Thread.currentThread().getName()+" 已加锁,开始写操作");
Thread.sleep(1000);
map.put(key,value);
}catch (Exception e){
e.printStackTrace();
}finally {
readLock.unlock();
System.out.println(Thread.currentThread().getName()+" 已解锁,写操作执行完成");
}
}
public static void main(String[] args) {
final ReadWriteDemo readWriteDemo = new ReadWriteDemo();
readWriteDemo.set("key1","value1");
new Thread(()->{
System.out.println(readWriteDemo.get("key1"));
},"读线程1").start();
new Thread(()->{
System.out.println(readWriteDemo.get("key1"));
},"读线程2").start();
new Thread(()->{
System.out.println(readWriteDemo.get("key1"));
},"读线程3").start();
}
}
运行结果: