排它锁,又称为独占锁、独享锁
共享锁,又称为读锁,获得共享锁后,可以查看但无法修改和删除数据,其他线程此时也可以获取到共享锁,也可以查看但无法修改和删除数据
共享锁和排它锁的典型是读写锁ReentrantReadWriteLock,其中读锁是共享锁,写锁是独享锁
读写锁的规则
- 多个线程只申请读锁,都可以申请到
- 如果有一个线程已占用读锁,则此时其他线程如果要申请写锁,则申请写锁的线程会一直等待释放读锁。
- 如果已占用了写锁,则此时其他线程如果申请写锁或读锁,则申请的线程会一直等待释放写锁
- 要么多读,要么一写
package lock.reentrantlock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class CinemaReadWrite {
private static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
private static ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
private static ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();
private static void read(){
readLock.lock();
try{
System.out.println(Thread.currentThread().getName()+"我得到了读锁,正在读取");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName()+"释放读锁");
readLock.unlock();
}
}
private static void write(){
writeLock.lock();
try{
System.out.println(Thread.currentThread().getName()+"我得到了写锁,正在写入");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName()+"释放写锁");
writeLock.unlock();
}
}
public static void main(String[] args) {
new Thread(()->read(),"Thread1").start();
new Thread(new Runnable() {
@Override
public void run() {
read();
}
}, "Thread2").start();
new Thread(()->write(),"Thread3").start();
new Thread(()->write(),"Thread4").start();
}
}
插队策略
公平锁:不允许插队
非公平锁:写锁可以随时插队。读锁仅在等待队列头时不是想获取写锁的线程的时候可以插队
升降级策略
只能降级,不能升级
适用于读多写少的情况