ReentrantLock 重入锁

3 篇文章 0 订阅
2 篇文章 0 订阅

锁分类参考文章

基本使用

1.继承与实现

public class ReentrantLock implements Lock, java.io.Serializable 

Lock 接口

// 如果锁可用就获得锁,如果锁不可用就阻塞直到锁释放
void lock();
// 和lock()方法相似, 但阻塞的线程 可 中 断 , 抛 出java.lang.InterruptedException 异常
void lockInterruptibly() throws InterruptedException;
// 非阻塞获取锁;尝试获取锁,如果成功返回 true
boolean tryLock();
//带有超时时间的获取锁方法
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
// 释放锁
void unlock();
Condition newCondition();

2.ReentrantLock 重入锁

重入锁,表示支持重新进入的锁,也就是说,如果当前线程 t1 通过调用 lock 方法获取了锁之后,再次调用 lock,是不会再阻塞去获取锁的,直接增加重试次数就行了。synchronized 和 ReentrantLock 都是可重入锁。

  • 可中断
  • 可以设置超时时间
  • 可以设置为公平锁
  • 支持多个条件变量

基本语法

	//获取锁
	reetrantLock.lock();
	try{
	    //临界区
	}finally{
	    //释放锁
	    reentrantLock.unlock();
	}

可重入

可重入指一个线程如果首次获取这把锁,他就是这把锁的拥有者,有权再次获取这把锁。如果是不可重入锁,那么第二次获得锁时,自己也会被锁挡住。

可打断

如果用的lock.lockInterruptibly()这个方法上锁的话,别的线程是可以通过interrupt方法打断的。比如:我的a线程正在尝试获取锁,但这个lock已经被b线程拿了,b可以如果执行Interrupt就可以把a线程正在尝试的打断直接获取失败不等待。就是一种防止无限制等待的机制,避免死等,减少死锁的产生。

锁超时

有个lock.tryLock()方法,返回boolean,获取到就返回true,获取不到锁就返回false,这个方法的可以传入两个参数超时时间,第一个参数数字代表时间,第二个是单位。代表他去tryLock()尝试获取锁的时候最多等待的实践,如果是1和秒就是最多尝试等待一秒,还没拿到就返回false。也是一直超时机制,防止死锁。

公平锁

syn就是非公平的,重量级的monitor的堵塞队列就是非公平的。
ReentrantLock默认是不公平,但是我们可以通过构造方法改成公平的,传的是boolean值

条件变量

syn不满足条件的线程都在一个休息室
而ReentranLock支持多休息室,唤醒的时候也是按照休息室来唤醒
使用流程:

  • await进行等待(前需要获得锁)
  • await执行后,会释放锁,进入conditionObject等待
  • await的线程被唤醒(或打断或超时)去重新竞争lock锁
  • 竞争lock锁成功后,从await后继续执行

在new完ReentranLock之后可以用newCondition()方法创建休息室,然后就可以用new出来的condition调用await方法进入休息室等待,唤醒的话是signal()方法

3.可调用的方法

在这里插入图片描述

4.构造

	public ReentrantLock() {
        sync = new NonfairSync();
    }
    //fair true 创建公平锁
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

5.获取锁

	//获取锁,获取不到,会等待知道获取
	public void lock() {
        sync.lock();
    }
    //可被其它线程打断的锁
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }
    //直接获取锁,成功则返回true 失败返回fasle
    public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
    }
    //指定时间范围获取锁,传入超时时间和单位
    public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }

6.释放锁

	public void unlock() {
        sync.release(1);
    }

7.查看锁的状态

	//查询此锁是否由任何线程持有。此方法设计用于监视系统状态,而不是用于同步控制。
	public boolean isLocked() {
        return sync.isLocked();
    }

8.是否是公平锁

	public final boolean isFair() {
        return sync instanceof FairSync;
    }

9.tostring

	//返回类型名@hashcode值,是否被锁,锁着的时候返回线程名
	//java.util.concurrent.locks.ReentrantLock@30ee82d7[Locked by thread Thread-0]
	public String toString() {
        Thread o = sync.getOwner();
        return super.toString() + ((o == null) ?
                                   "[Unlocked]" :
                                   "[Locked by thread " + o.getName() + "]");
    }

测试使用

public class Test5 {
	static ReentrantLock reentrantLock = new ReentrantLock();
	static Test5 test5;
	static Thread thread1;
	public static int a = 5;
	public void test() {
		System.err.println("hashCode"+reentrantLock.hashCode());
		boolean tryLock;
		try {
			tryLock = reentrantLock.tryLock(5, TimeUnit.SECONDS);
			System.err.println("getHoldCount:"+reentrantLock.hasQueuedThreads());
			
			/*Condition newCondition = reentrantLock.newCondition();
			newCondition.awaitUninterruptibly();*/
			System.out.println("线程"+Thread.currentThread().getName()+":开始调用Test5");
			System.out.println("线程"+Thread.currentThread().getName()+":拿到锁"+reentrantLock.isLocked());
			if(!tryLock)
				return;
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		try {
			try {
				for (int i = 0; i < 20; i++) {
					Thread.sleep(10);
					a++;
					System.out.println("线程"+Thread.currentThread().getName()+":"+ a);
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} finally {
			System.out.println("线程"+Thread.currentThread().getName()+":释放锁");
			reentrantLock.unlock();
		}
	}
	public static void main(String[] args) {
		
		thread1 = new Thread() {
			public void run() {
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				test5 = new Test5();
				test5.test();
				
			};
		};
		thread1.start();
		
		new Thread() {
			public void run() {
				test5 = new Test5();
				test5.test();
			};
		}.start();
		
		new Thread() {
			public void run() {
				try {
					Thread.sleep(60);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.err.println("getHoldCount:"+reentrantLock.getHoldCount());
			};
		}.start();
	}
}

源码实现

1.Sync

abstract static class Sync extends AbstractQueuedSynchronizer 
		abstract void lock();
		final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }
        protected final boolean isHeldExclusively() {
            // While we must in general read state before owner,
            // we don't need to do so to check if current thread is owner
            return getExclusiveOwnerThread() == Thread.currentThread();
        }
        final ConditionObject newCondition() {
            return new ConditionObject();
        }
        // Methods relayed from outer class
        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }
        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
        }
        final boolean isLocked() {
            return getState() != 0;
        }
        /**
         * Reconstitutes the instance from a stream (that is, deserializes it).
         */
        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }

2.NonfairSync

	static final class NonfairSync extends Sync{
		private static final long serialVersionUID = 7316153563782823691L;
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);//AbstractQueuedSynchronizer 的方法
        }
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }}

3.FairSync

	static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;
        final void lock() {
            acquire(1);
        }
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

下篇文章继续学习

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值