侧边栏壁纸
  • 累计撰写 91 篇文章
  • 累计创建 35 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

java ReentrantLock

天明
2023-10-25 / 0 评论 / 0 点赞 / 29 阅读 / 3684 字 / 正在检测是否收录...

ReentrantLock和synchronized的相同点

1.ReentrantLock和synchronized都是独占锁,只允许线程互斥的访问临界区。但是实现上两者不同:synchronized加锁解锁的过程是隐式的,用户不用手动操作,优点是操作简单,但显得不够灵活。一般并发场景使用synchronized的就够了;ReentrantLock需要手动加锁和解锁,且解锁的操作尽量要放在finally代码块中,保证线程正确释放锁。ReentrantLock操作较为复杂,但是因为可以手动控制加锁和解锁过程,在复杂的并发场景中能派上用场。

2.ReentrantLock和synchronized都是可重入的。synchronized因为可重入因此可以放在被递归执行的方法上,且不用担心线程最后能否正确释放锁;而ReentrantLock在重入时要却确保重复获取锁的次数必须和重复释放锁的次数一样,否则可能导致其他线程无法获得该锁。

ReentrantLock公平锁

公平锁是指当锁可用时,在锁上等待时间最长的线程将获得锁的使用权。而非公平锁则随机分配这种使用权。和synchronized一样,默认的ReentrantLock实现是非公平锁,因为相比公平锁,非公平锁性能更好。当然公平锁能防止饥饿,某些情况下也很有用。在创建ReentrantLock的时候通过传进参数true创建公平锁,如果传入的是false或没传参数则创建的是非公平锁

例子

public class Java_ReentrantLock {

	public void test() throws InterruptedException {
		// ReentrantLock是独占锁且可重入的
		ReentrantLock lock = new ReentrantLock();
		for (int i = 1; i <= 3; i++) {
			lock.lock();
		}
		for (int i = 1; i <= 3; i++) {
			try {
			} finally {
				lock.unlock();
			}
		}
	}

	public void test1() {
		// 场景 1:如果发现该操作已经在执行中则不再执行(有状态执行)
		ReentrantLock lock = new ReentrantLock();
		if (lock.tryLock()) { // 如果已经被 lock,则立即返回 false 不会等待,达到忽略操作的效果。
			try {
				// 操作
			} finally {
				lock.unlock();
			}

		}
	}

	public void test2() {
		// 场景 2:如果发现该操作已经在执行,等待一个一个执行(同步执行,类似 synchronized)
		// 公平情况下,操作会排一个队按顺序执行,来保证执行顺序。(会消耗更多的时间来排队)
		// 不公平情况下,是无序状态允许插队,JVM 会自动计算如何处理更快速来调度插队。(如果不关心顺序,这个速度会更快)
		ReentrantLock lock = new ReentrantLock(); // 参数默认false,不公平锁
		// ReentrantLock lock = new ReentrantLock(true); //公平锁
		try {
			lock.lock(); // 如果被其它资源锁定,会在此等待锁释放,达到暂停的效果
			// 操作
		} finally {
			lock.unlock();
		}
	}

	public void test3() {
		// 场景 3:如果发现该操作已经在执行,则尝试等待一段时间,等待超时则不执行(尝试等待执行)
		ReentrantLock lock = new ReentrantLock();
		try {
			if (lock.tryLock(5, TimeUnit.SECONDS)) { // 如果已经被 lock,尝试等待
														// 5s,看是否可以获得锁,如果 5s
														// 后仍然无法获得锁则返回 false
														// 继续执行
				try {
					// 操作
				} finally {
					lock.unlock();
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace(); // 当前线程被中断时(interrupt),会抛 InterruptedException
		}
	}

	public void test4() {
		// 场景 5:条件判断。
		// 每一个 lock 可以有任意数据的 Condition 对象
		Lock lock = new ReentrantLock();
		Condition condition = lock.newCondition();
		lock.lock();
		try {
			boolean cnd = false;
			while (cnd) {
				condition.wait();
			}
			// 处理逻辑
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
}
0

评论区