Lock
Lock implementations provide more extensive locking operations than can be obtained using synchronized methods and statements. They allow more flexible structuring, may have quite different properties, and may support multiple associated Condition objects.
锁实现提供了比使用同步方法和语句可以获得的更广泛的锁操作。它们允许更灵活的结构,可能具有非常不同的属性,并且可能支持多个关联的条件对象。
ReentrantLock
ReentrantLock一个可重入的互斥锁,它具有与隐式锁synchronized相同的一些基本行为和语义,但功能能强大。
如何使用
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}
synchronized与Lock的区别
- 首先synchronized是java内置关键字,在jvm层面,Lock是个Java类;
- synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
- synchronized会自动释放(a线程执行完同步代码会释放锁;b线程执行过程中发生异常会释放锁),Lock需要在finally中手动释放锁(unlock()方法释放锁),否则容易造成死锁;
- 用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2等待。如果线程1阻塞,线程2则会一直等待下去。而Lock就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就会结束了;
- synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可中断、可公平(两者皆可)
- Lock lock = new ReentrantLock(true);//创建lock锁 ture 是公平锁,false是非公平锁
- Lock锁适合大量同步的代码的同步问题,synchronize锁适合代码少量的同步问题。
ReadWriteLock
ReadWriteLock 接口只有两个方法,一个是只读锁,一个是写锁。
读写锁表示两个锁:
读操作相关的锁,也叫共享锁。
写操作相关的锁,也叫排他锁。
多个读锁之间不互斥,读锁也写锁互斥,多个写锁互斥。
举个例子
class MyCache {
private volatile Map<String, Object> map = new HashMap<>();
private ReadWriteLock rwLock = new ReentrantReadWriteLock();
public void put(String key, Object value) {
rwLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() +"\t 正在写"+ key);
//暂停一会儿线程
try {
TimeUnit.MILLISECONDS.sleep(300);
}catch(InterruptedException e) {
e.printStackTrace();
}
map.put(key, value);
System.out.println(Thread.currentThread().getName() +"\t 写完了"+ key);
}catch(Exception e) {
e.printStackTrace();
}finally{
rwLock.writeLock().unlock();
}
}
public Object get(String key) {
rwLock.readLock().lock();
Object result = null;
try {
System.out.println(Thread.currentThread().getName() +"\t 正在读"+ key);
try{
TimeUnit.MILLISECONDS.sleep(300);
}catch(InterruptedException e) {
e.printStackTrace();
}
result = map.get(key);
System.out.println(Thread.currentThread().getName() +"\t 读完了"+ result);
}catch(Exception e) {
e.printStackTrace();
}finally{
rwLock.readLock().unlock();
}
return result;
}
}
public class ReadWriteLockDemo {
public static void main(String args[]){
MyCache myCache = new MyCache();
for (int i = 1; i <= 5; i++) {
final int num = i;
new Thread(() -> {
myCache.put(num+"",num+"");
},String.valueOf(i)).start();
}
for (int i = 1; i <= 5; i++) {
final int num = i;
new Thread(() -> {
myCache.get(num+"");
},String.valueOf(i)).start();
}
}
}