ReentrantLock在加锁和内存上提供的语义与内置锁相同,林外它提供了一些其他功能,包括定时的锁等待、可中断的锁等待、公平性,以及实现非块结构的加锁。
与显示锁相比,内置锁仍然具有很大的优势。内置锁为许多开发人员所熟悉,并且简洁紧凑。ReentrantLock的危险性比同步机制要高,如果忘记在finally块中调用unlock,,虽然代码表面能正常运行,但实际上已经埋下了一课定时炸弹。
在内置锁无法满足需求的情况下,ReentrantLock可作为一种高级工具,当需要一种高级功能时,才应该使用ReentrantLock,这些功能包括:可定时的,可轮询的与可中断的锁获取操作,公平队列,以及非块结构操作的锁,否则,还是应该优先使用synchronized。
接下来ReentrantLock类中是方法lockInterruptibly()、tryLock()、tryLock(Long timeout,TimeUnit unit)的介绍
1lockInterruptibly()
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class MyService {
public ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void waitMethod() {
try {
lock.lock();
System.out
.println("lock begin " + Thread.currentThread().getName());
for (int i = 0; i < Integer.MAX_VALUE / 10; i++) {
String newString = new String();
Math.random();
}
System.out
.println("lock end " + Thread.currentThread().getName());
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
public class Run {
public static void main(String[] args) throws InterruptedException {
final MyService service = new MyService();
Runnable runnableRef = new Runnable() {
@Override
public void run() {
service.waitMethod();
}
};
Thread threadA = new Thread(runnableRef);
threadA.setName("A");
threadA.start();
Thread.sleep(500);
Thread threadB = new Thread(runnableRef);
threadB.setName("B");
threadB.start();
threadB.interrupt();// ����
System.out.println("main end!");
}
}
打印结果
lock begin A
main end!
lock end A
lock begin B
lock end B
因为前面使用的是lock.lock(),正常执行
下面使用lock.lockInterruptibly()方法。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class MyService {
public ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void waitMethod() {
try {
lock.lockInterruptibly();
System.out
.println("lock begin " + Thread.currentThread().getName());
for (int i = 0; i < Integer.MAX_VALUE / 10; i++) {
String newString = new String();
Math.random();
}
System.out
.println("lock end " + Thread.currentThread().getName());
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
public class Run {
public static void main(String[] args) throws InterruptedException {
final MyService service = new MyService();
Runnable runnableRef = new Runnable() {
@Override
public void run() {
service.waitMethod();
}
};
Thread threadA = new Thread(runnableRef);
threadA.setName("A");
threadA.start();
Thread.sleep(500);
Thread threadB = new Thread(runnableRef);
threadB.setName("B");
threadB.start();
threadB.interrupt();// ����
System.out.println("main end!");
}
}
打印结果
lock A
线程B进入catch~!
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1199)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:312)
at service.MyService.waitMethod(MyService.java:13)
at test.Run$1.run(Run.java:12)
at java.lang.Thread.run(Thread.java:695)
2tryLock()
package service;
import java.util.concurrent.locks.ReentrantLock;
public class MyService {
public ReentrantLock lock = new ReentrantLock();
public void waitMethod() {
if (lock.tryLock()) {
System.out.println(Thread.currentThread().getName() + "获得锁");
} else {
System.out.println(Thread.currentThread().getName() + "没有获得锁");
}
}
}
package test;
import service.MyService;
public class Run {
public static void main(String[] args) throws InterruptedException {
final MyService service = new MyService();
Runnable runnableRef = new Runnable() {
@Override
public void run() {
service.waitMethod();
}
};
Thread threadA = new Thread(runnableRef);
threadA.setName("A");
threadA.start();
Thread threadB = new Thread(runnableRef);
threadB.setName("B");
threadB.start();
}
}
打印结果
A获得锁
B没有获得锁
3tryLock(Long timeout,TimeUnit unit)
这个方法的作用是在给定等待时间内一直尝试获取锁并返回true,若超过时间则返回false
package service;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class MyService {
public ReentrantLock lock = new ReentrantLock();
public void waitMethod() {
try {
if (lock.tryLock(2, TimeUnit.SECONDS)) {
System.out.println(" " + Thread.currentThread().getName()
+ "获得锁的时间:"+ System.currentTimeMillis());
Thread.sleep(2000);
} else {
System.out.println(" " + Thread.currentThread().getName()
+ "没有获得锁");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
package test;
import service.MyService;
public class Run {
public static void main(String[] args) throws InterruptedException {
final MyService service = new MyService();
Runnable runnableRef = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()
+ "调用waitMethod时间" + System.currentTimeMillis());
service.waitMethod();
}
};
Thread threadA = new Thread(runnableRef);
threadA.setName("A");
threadA.start();
Thread threadB = new Thread(runnableRef);
threadB.setName("B");
threadB.start();
}
}
打印结果
A调用waitMethod时间1532006068749
B调用waitMethod时间1532006068749
A获得锁的时间:1532006068750
B没有获得锁