Java高并发26-释放锁以及ReentrantLock实例演示

一、释放锁

1.void unlock()方法

  • 尝试释放锁,如果当前线程持有锁,则调用该方法会让该线程对该线程持有的AQS状态值减1,如果减去1后当前状态值为0,则当前线程会释放该锁,否则仅仅减去1而已,如果当前线程没有持有该锁而调用了该方法就会抛出IllegalMonitorStateException异常,代码如下
	public void unlock() {
		sync.release();
	}
	
	public final boolean tryRelease( int releases) {
		// 如果不是锁持有者,则调用 unlock则抛出异常
		int c = getState() - releases;
		if(Thread.currentThread() != getExclusiveOwnerThread()) {
			throw new IllegalMonitorStateException();
		}
		boolean free = false;
		// 如果当前可重入的次数为0,则清空锁持有线程
		if(c == 0) {
			free = true;
			setExclusiveOwnerThread(null);
		}
		// 设置可重入次数为原始值-1
		setState(c);
		return free;
	}
  • 如上述代码,如果当前线程不是该锁的持有者则直接抛出异常,否则查看状态值是否为0,为0则说明当前线程要放弃对该锁的持有权,则执行代码把当前锁的持有者设置为null,如果状态值不为0,则仅仅让当前线程对该锁的可重入次数减1.

2.下面以一个案例作为讲解

package com.ruigege.LockSourceAnalysis6;

import java.util.ArrayList;

public static class ReentrantLockList {

	//线程不安全的List
	private ArrayList<String> array = new ArrayList<String>();
	//独占锁
	private volatile ReentrantLock lock = new ReentrantLock();
	
	//添加元素
	public void add(String e) {
		lock.lock();
		try {
			array.add(e);
		}finally {
			lcok.unlock();
		}
	}
	//删除元素
	public void remove(String e) {
		lock.lock();
		try {
			array.remove(e);
		}finally {
			lock.unlock();
		}
	}
	
	//获取数据
	public String get(int index) {
		lock.lock();
		try {
			return array.get(index);
		}finally {
			lock.unlock();
		}
	}
}
  • 上述代码实现了一个线程不安全的array,当一个线程获取到锁的时候,进行一系列的增删改查,如果有其他线程想要获取到该锁,那么就会被放到AQS的队列中,等待第一个线程释放锁,来供它们获取。

二、读写锁ReentrantReadWriteLock的原理

  • 解决线程安全问题只需要ReentrantLock即可,但是大多数情况下,该锁是独占锁,某时只有一个线程可以获取到该锁,那么实际上大多情况是写少读多,显然这个场景是无法满足的。所以ReentrantReadWriteLock就应运而生了,ReentrantReadWriteLock采用的时读写分离的策略,可以允许多个线程同时获取锁。
  • 我们下次再来解析这个类

三、源码:

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值