ReentrantLock可重入锁

目录

在Java并发编程中经常会用到各种类型的锁,比如乐观锁、悲观锁、自旋锁、可重入锁、轮询锁、定时锁、读写锁等,锁是解决并发冲突的重要工具。本文对ReentrantLock可重入锁进行重点介绍,其余锁类型后续将在其他文章中分别介绍。

ReentrantLock可重入锁定义

可重入锁指的是 可重复可递归调用 的锁,ReentrantLock是JAVA SE 5.0时引入的互斥锁,由java.util.concurrent框架提供。

ReentrantLock支持公平锁和非公平锁

ReentrantLock实现了lock接口,有两个构造方法,一个是无参的 ReentrantLock() ,另一个带布尔类型参数public ReentrantLock(boolean fair)。其中 fair为true实现公平锁,无参或者fair为false实现非公平锁
公平锁与非公平锁的区别主要在线程获取锁的规则,公平锁是按照线程加锁的顺序,即等待时间最长的线程将优先获得锁,符合FIFO(先进先出)的规则;非公平锁则是线程随机获得锁。公平锁能避免线程饥饿,非公平锁性能更好。其中线程饥饿指的是线程一直无法获得其所需的资源而导致其任务一直无法进展的一种活性故障。

ReentrantLock线程等待简单示例

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockSample {
	static ReentrantLock lock = new ReentrantLock();
	static Condition condition = lock.newCondition();
	
	public static void main(String args[]) throws InterruptedException{
		
		lock.lock();
		System.out.println("Main Thread Begin");
		new Thread(new Runnable(){

			@Override
			public void run() {
				// TODO Auto-generated method stub
				lock.lock(); 
				condition.signal();
				System.out.println("Sub Thread Run");
				lock.unlock();
			}
			
		}).start();
		condition.await();
		lock.unlock();
		System.out.println("Main Thread End");
	}
}

示例主要介绍了通过Condition接口实现线程间的等待通知机制,其中使用Conditon接口前,需要通过lock()方法获得锁,然后调用Condition接口的await方法使得当前线程进入等待状态,并等待其他线程调用Condition接口的signal方法唤醒该线程。

ReentrantLock响应中断方式与限时等待

ReentrantLock支持 响应中断 方式获取锁,即调用ReentrantLock的 lockInterruptibly 方法进行获取,必要时可以通过调用进程的interrupt()方法中断等待,抛出InterruptedException异常。
ReentrantLock也支持 限时等待 获取锁,通过调用ReentrantLock的 trylock 方法进行获取,trylock不带参数表明立即返回获取锁的结果,带参数则表示在指定时间间隔获取锁,获取成功返回true,失败返回false。

ReentrantLock中Lock与TryLock的区别

Lock.lock()始终等待不能被interrupt打断;
Lock.lockInterruptibly()进行等待,但可能被interrupt中断等待;
Lock.trylock()不会等待,直接返回获取锁的结果;
Lock.tryLock(long time, TimeUnit unit)在指定时间内可被interrupt打断,如果指定时间内获取到锁返回true,超过指定时间否则返回false。

Lock和Synchronized的区别

类型:Lock是接口,Synchronized是关键字。
范围:Lock作用于代码块,Synchronized作用于类、方法、代码块。
中断:Lock可以让等待锁的线程响应式中断,Synchronized的会一直等待下去。
释放:Lock需要手动释放锁,Synchronized会自动释放锁。
效率:Lock相对可以Synchronized提高读的效率。
公平与非公平锁:Lock实现可重入、可中断、公平或非公平锁,Synchronized实现可重入、不可中断、非公平锁。
线程有无拿到锁:Lock可以知道线程有没拿到锁,Synchronized则不行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,针对第二个问题的线程同步问题,我们可以使用同步方法和ReentrantLock可重入锁两种方式来解决。 ### 1. 同步方法 使用同步方法可以保证在同一时刻只有一个线程能够访问被synchronized关键字修饰的方法。在本例中,我们可以将withdraw和deposit方法都声明为同步方法,如下所示: ```java public synchronized void withdraw(double amount){ if (balance >= amount) { balance -= amount; System.out.println(Thread.currentThread().getName() + " withdraws " + amount + ", balance is " + balance); } else { System.out.println(Thread.currentThread().getName() + " withdraws failed, balance is " + balance); } } public synchronized void deposit(double amount){ if (amount > 0) { balance += amount; System.out.println(Thread.currentThread().getName() + " deposits " + amount + ", balance is " + balance); } else { System.out.println(Thread.currentThread().getName() + " deposits failed, balance is " + balance); } } ``` ### 2. ReentrantLock可重入锁 ReentrantLock可重入锁是一种更加灵活的线程同步方式,它比synchronized关键字提供了更多的功能,如公平、可中断、多条件变量等。在本例中,我们可以使用ReentrantLock来保证在同一时刻只有一个线程能够访问被住的代码块。具体实现如下: ```java private final ReentrantLock lock = new ReentrantLock(); public void withdraw(double amount){ lock.lock(); try { if (balance >= amount) { balance -= amount; System.out.println(Thread.currentThread().getName() + " withdraws " + amount + ", balance is " + balance); } else { System.out.println(Thread.currentThread().getName() + " withdraws failed, balance is " + balance); } } finally { lock.unlock(); } } public void deposit(double amount){ lock.lock(); try { if (amount > 0) { balance += amount; System.out.println(Thread.currentThread().getName() + " deposits " + amount + ", balance is " + balance); } else { System.out.println(Thread.currentThread().getName() + " deposits failed, balance is " + balance); } } finally { lock.unlock(); } } ``` 在以上代码中,我们使用了ReentrantLocklock()和unlock()方法来手动加和解代码块。使用try-finally语句块的方式可以确保即使在代码块执行过程中出现异常,也能够被正确释放。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值