可重入锁
首先明白可重入锁的概念:就是在一个线程中可以重复加锁
在一个线程中可以重复加锁,使用的ReentrantLock()就是一种可重入锁
例子:
public static void main(String[] args) throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
lock.lock();
lock.lock();
System.out.println("当前锁个数"+lock.getHoldCount()+"锁"+lock.isLocked());
lock.unlock();
System.out.println("当前锁个数"+lock.getHoldCount()+"锁是否被释放"+lock.isLocked());
lock.unlock();
System.out.println("当前锁个数"+lock.getHoldCount()+"锁是否被释放"+lock.isLocked());
}
getHoldCount()用来查看当前线程的加锁次数。isLocked()用来查看当前线程是否有锁
实际上当一个线程持有锁的时候,其他线程想要获取锁会进入一个等待队列的
可以使用getQueueLength()来获取当前等待获取锁的线程数
例子:
public static void main(String[] args) throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
Thread t1 = new Thread(lock::lock), t2 = new Thread(lock::lock),t3 = new Thread(lock::lock);
t1.start();
t2.start();
t3.start();
TimeUnit.SECONDS.sleep(1);
System.out.println("当前等待锁释放的线程数:"+lock.getQueueLength());
System.out.println("线程1是否在等待队列中:"+lock.hasQueuedThread(t1));
System.out.println("线程2是否在等待队列中:"+lock.hasQueuedThread(t2));
System.out.println("线程3是否在等待队列中:"+lock.hasQueuedThread(t3));
System.out.println("当前线程是否在等待队列中:"+lock.hasQueuedThread(Thread.currentThread()));
}
// 当前等待锁释放的线程数:2
// 线程1是否在等待队列中:false
// 线程2是否在等待队列中:true
// 线程3是否在等待队列中:true
// 当前线程是否在等待队列中:false
可以看到2,3线程都在等待队列中
公平锁和非公平锁
前面我们知道,当出现多个线程争抢一把锁的时候会进入等待队列,那么争抢的顺序一定是按,获取锁的代码顺序来的吗?
来看看ReentrantLock的构造方法
public ReentrantLock() {
sync = new NonfairSync(); //看名字貌似是非公平的
}
其实锁可以分为公平锁和非公平锁,上面的实现类默认采用的是非公平锁
- 公平锁:多个线程按照申请锁的顺序依次进入队列,永远是第一个进入的先获取到缩进
- 非公平锁:当一个线程要获取锁的时候,直接先去尝试获取锁,如果得到了,那就不进入等待队列,没有得到的话就进入等待队列
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
这是另外一种构造方法,用来确定是哪一种锁
例子
public static void main(String[] args) throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
Runnable action = () -> {
System.out.println(Thread.currentThread().getName() + " is running");
lock.lock();
System.out.println(Thread.currentThread().getName() + " is locked");
lock.unlock();
};
for (int i = 0; i < 10; i++) {
new Thread(action,"T"+i).start();
}
}
// T0 is running
// T3 is running
// T2 is running
// T1 is running
// T5 is running
// T0 is locked
// T4 is running
// T4 is locked
// T6 is running
// T7 is running
// T6 is locked
// T8 is running
// T3 is locked
// T9 is running
// T2 is locked
// T1 is locked
// T5 is locked
// T7 is locked
// T8 is locked
// T9 is locked
可以看到T4在T0释放锁之后获取了锁,这显然和顺序是不同的,如果是顺序的话,那么应该是T3先获取锁才对
再来看公平锁,直接将参数改为true
ReentrantLock lock = new ReentrantLock(true);
// T0 is running
// T4 is running
// T3 is running
// T6 is running
// T1 is running
// T7 is running
// T2 is running
// T8 is running
// T0 is locked
// T5 is running
// T9 is running
// T4 is locked
// T3 is locked
// T6 is locked
// T1 is locked
// T7 is locked
// T2 is locked
// T8 is locked
// T5 is locked
// T9 is locked
可以看到这边就是按顺序的获取锁
t0->t4->t3->t6...
以上就是关于文章的全部内容,希望对你有所帮助!!!