tryLock尝试获取锁
package lock.lock;import java.util.Random;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** 描述: 用tryLock来避免死锁*/
public class TryLockDeadlock implements Runnable {int flag = 1;static Lock lock1 = new ReentrantLock();static Lock lock2 = new ReentrantLock();public static void main(String[] args) {TryLockDeadlock r1 = new TryLockDeadlock();TryLockDeadlock r2 = new TryLockDeadlock();r1.flag = 1;r1.flag = 0;new Thread(r1).start();new Thread(r2).start();}@Overridepublic void run() {for (int i = 0; i < 100; i++) {if (flag == 1) {try {if (lock1.tryLock(800, TimeUnit.MILLISECONDS)) {try {System.out.println("线程1获取到了锁1");Thread.sleep(new Random().nextInt(1000));if (lock2.tryLock(800, TimeUnit.MILLISECONDS)) {try {System.out.println("线程1获取到了锁2");System.out.println("线程1成功获取到了两把锁");break;} finally {lock2.unlock();}} else {System.out.println("线程1获取锁2失败,已重试");}} finally {lock1.unlock();Thread.sleep(new Random().nextInt(1000));}} else {System.out.println("线程1获取锁1失败,已重试");}} catch (InterruptedException e) {e.printStackTrace();}}if (flag == 0) {try {if (lock2.tryLock(3000, TimeUnit.MILLISECONDS)) {try {System.out.println("线程2获取到了锁2");Thread.sleep(new Random().nextInt(1000));if (lock1.tryLock(800, TimeUnit.MILLISECONDS)) {try {System.out.println("线程2获取到了锁1");System.out.println("线程2成功获取到了两把锁");break;} finally {lock1.unlock();}} else {System.out.println("线程2获取锁1失败,已重试");}} finally {lock2.unlock();Thread.sleep(new Random().nextInt(1000));}} else {System.out.println("线程2获取锁2失败,已重试");}} catch (InterruptedException e) {e.printStackTrace();}}}}
}
ReentrantLock的tryLock方法是对Lock接口的tryLock实现
应用场景
非阻塞的场景,允许某些任务不执行(比如防止重复提交业务),或超时不执行(比如防止资源等待队列溢出)等
不带参数的 tryLock
public boolean tryLock() {return sync.nonfairTryAcquire(1);
}
实现比较简单,内部调用sync#nonfairTryAcquire方法,该方法前篇分析lock方法的时候已经解析过了在此不做赘述
带超时和支持中断响应的 tryLock
/*** Acquires the lock if it is free within the given waiting time and the* current thread has not been {@linkplain Thread#interrupt interrupted}.*(在指定的时间内获取锁如果锁未被其他线程持有,并且这个线程没有被中断)* If the lock is available this method returns immediately* with the value {@code true}.*(如果锁是可用的这个方法会立刻返回true)* If the lock is not available then* the current thread becomes disabled for thread scheduling* purposes and lies dormant until one of three things happens:* (如果锁是不可用的那么当前线程将不可用对于线程调度,并且会休眠直到1件或3件事情发生)*
* - The lock is acquired by the current thread; or*
- Some other thread {@linkplain Thread#interrupt interrupts} the* current thread, and interruption of lock acquisition is supported; or*
- The specified waiting time elapses*
*(这个锁被当前线程持有;或者其他的线程中断了当前线程,并且锁的中断是被支持的;或者指定的等待时间超时)* If the lock is acquired then the value {@code true} is returned.*(如果这个锁被获取那么将返回true)*
If the current thread:*
* - has its interrupted status set on entry to this method; or*
- is {@linkplain Thread#interrupt interrupted} while acquiring* the lock, and interruption of lock acquisition is supported,*
* then {@link InterruptedException} is thrown and the current thread's* interrupted status is cleared.* 如果线程被中断将抛出InterruptedException异常* If the specified waiting time elapses then the value {@code false}* is returned.* If the time is* less than or equal to zero, the method will not wait at all.*(如果指定的等待时间到了还未获取到锁将返回false,如果指定的时间少于或者等于0,方法将不会等待)*
Implementation Considerations*(实现的注意事项)*
The ability to interrupt a lock acquisition in some implementations* may not be possible, and if possible may* be an expensive operation.* The programmer should be aware that this may be the case. An* implementation should document when this is the case.*(在某些实现中中断锁获取的能力可能不可能,并且可能的话是一个昂贵的操作。程序员应该意识到情况可能是这样的。一个在这种情况下,实现应该记录下来。)*
An implementation can favor responding to an interrupt over normal* method return, or reporting a timeout.*(一个实现可以响应一个中断,或者报告超时)*
A {@code Lock} implementation may be able to detect* erroneous use of the lock, such as an invocation that would cause* deadlock, and may throw an (unchecked) exception in such circumstances.* The circumstances and the exception type must be documented by that* {@code Lock} implementation.*(实现可能会检测到锁的错误使用,例如可能导致死锁的调用,并可能在这种情况下引发(未经检查的)异常。这种情况和异常类型必须由{@code lock}实现记录)* @param time the maximum time to wait for the lock (获取锁的最大等待时间)* @param unit the time unit of the {@code time} argument (时间单位)* @return {@code true} if the lock was acquired and {@code false}* if the waiting time elapsed before the lock was acquired*(如果锁被获取了返回true,如果等待时间超时还未获取则返回false)* @throws InterruptedException if the current thread is interrupted* while acquiring the lock (and interruption of lock* acquisition is supported)*(当前线程被中断了需要返回InterruptedException当获取锁的时候(并且锁的获取中断是被支持的))*/boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
查看ReentrantLock的实现
public boolean tryLock(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
sync#tryAcquireNanos 调用的是父类AbstractQueuedSynchronizer的tryAcquireNanos方法
/*** Attempts to acquire in exclusive mode, aborting if interrupted,* and failing if the given timeout elapses. Implemented by first* checking interrupt status, then invoking at least once {@link* #tryAcquire}, returning on success. Otherwise, the thread is* queued, possibly repeatedly blocking and unblocking, invoking* {@link #tryAcquire} until success or the thread is interrupted* or the timeout elapses. This method can be used to implement* method {@link Lock#tryLock(long, TimeUnit)}.** @param arg the acquire argument. This value is conveyed to* {@link #tryAcquire} but is otherwise uninterpreted and* can represent anything you like.* @param nanosTimeout the maximum number of nanoseconds to wait* @return {@code true} if acquired; {@code false} if timed out* @throws InterruptedException if the current thread is interrupted*/public final boolean tryAcquireNanos(int arg, long nanosTimeout)throws InterruptedException {//中断检测if (Thread.interrupted())throw new InterruptedException();//step1. 调用tryAcquire先尝试获取锁,如果失败则调用doAcquireNanosreturn tryAcquire(arg) ||doAcquireNanos(arg, nanosTimeout);}
AbstractQueuedSynchronizer#doAcquireNanos
/*** Acquires in exclusive timed mode.** @param arg the acquire argument* @param nanosTimeout max wait time* @return {@code true} if acquired*/private boolean doAcquireNanos(int arg, long nanosTimeout)throws InterruptedException {if (nanosTimeout <= 0L)return false;//计算出到期时间final long deadline = System.nanoTime() + nanosTimeout;//新增独占节点final Node node = addWaiter(Node.EXCLUSIVE);boolean failed = true;try {//反复重试直到成功获取锁或者超时返回falsefor (;;) {final Node p = node.predecessor();//该节点的前节点是头节点则尝试获取锁if (p == head && tryAcquire(arg)) {setHead(node);p.next = null; // help GCfailed = false;return true;}//剩余时间nanosTimeout = deadline - System.nanoTime();if (nanosTimeout <= 0L)//超时返回falsereturn false;//shouldParkAfterFailedAcquire 判断是否需要阻塞线程 并且剩余时间大于 spinForTimeoutThreshold (默认1000)if (shouldParkAfterFailedAcquire(p, node) &&nanosTimeout > spinForTimeoutThreshold)LockSupport.parkNanos(this, nanosTimeout);//中断检测if (Thread.interrupted())throw new InterruptedException();}} finally {if (failed)cancelAcquire(node);}}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
