ReentrantLock称之为可重入锁
- 是Lock的实现类,其中方法的功能已经介绍过了,不在赘述。
先上代码尝尝鲜
常规版
public class LockT {
private final Lock lock = new ReentrantLock(); //可重入锁
public void f1(){
try {
lock.lock();
System.out.println("正在执行f1");
}finally {
lock.unlock();
}
}
public void f2(){
try {
lock.lock();
System.out.println("正在执行f2");
}finally {
lock.unlock();
}
}
public static void main(String[] args) {
LockT T = new LockT();
new Thread(()-> {//该线程会执行f1()
for (int i = 0;i<10;i++){
T.f1();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(()-> {//该线程会执行f2()
for (int i = 0;i<10;i++){
T.f2();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
- 结果:
如果把f1()中lock.unlock();注释掉,会如何?
- 代码小改一丢丢
public class LockT {
private final Lock lock = new ReentrantLock(); //可重入锁
public void f1(){
try {
lock.lock();
System.out.println("正在执行f1");
}finally {
//lock.unlock(); //改了这
}
}
public void f2(){
try {
lock.lock();
System.out.println("正在执行f2");
}finally {
lock.unlock();
}
}
public static void main(String[] args) {
LockT T = new LockT();
new Thread(()-> {//该线程会执行f1()
for (int i = 0;i<10;i++){
T.f1();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(()-> {//该线程会执行f2()
for (int i = 0;i<10;i++){
T.f2();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
- 结果:
- 原因:
-
首先,
f1()没有释放锁(unlock),这就导致执行f2()的线程无法执行也就无法结束该程序 其次,这是可重入锁,这就导致执行f1()的线程在没有释放锁的情况下还可以再次获取锁,只能是没有释放锁的线程可以再次获取。
-
如果不想让线程永久阻塞可以试试tryLock()
public class LockT {
private final Lock lock = new ReentrantLock(); //可重入锁
public void f1(){
try {
lock.lock();
System.out.println("正在执行f1");
}finally {
//lock.unlock();
}
}
public void f2(){
boolean res = false ;
try {
res = lock.tryLock(1, TimeUnit.SECONDS);//在一分钟内没有获取到锁就执行else
} catch (InterruptedException e) {
e.printStackTrace();
}
if(res){
try {
System.out.println("f2获取到了锁");
} finally {
lock.unlock();
}
}
else{
System.out.println("f2没有获取到锁");
}
}
public static void main(String[] args) {
LockT T = new LockT();
new Thread(()-> {//该线程会执行f1()
for (int i = 0;i<10;i++){
T.f1();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(()-> {//该线程会执行f2()
for (int i = 0;i<10;i++){
T.f2();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
- 结果
在有正常释放锁的情况下试试tryLock()
- 顺便把main方法代中是sleep移到f()方法中
public class LockT {
private final Lock lock = new ReentrantLock(); //可重入锁
public void f1(){
try {
lock.lock();
System.out.println("正在执行f1");
Thread.sleep(1000);
}catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void f2(){
boolean res = false ;
try {
res = lock.tryLock(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(res){
try {
System.out.println("f2获取到了锁");
} finally {
lock.unlock();
}
}
else{
System.out.println("f2没有获取到锁");
}
}
public static void main(String[] args) {
LockT T = new LockT();
new Thread(()-> {//该线程会执行f1()
for (int i = 0;i<10;i++){
T.f1();
}
}).start();
new Thread(()-> {//该线程会执行f2()
for (int i = 0;i<10;i++){
T.f2();
}
}).start();
}
}
- 结果:
小结
- 本篇只介绍了
ReentrantLock常规的一些方法,还有一些其他方法lockInterruptibly()和另外有关该类的构造方法ReentrantLock(boolean fair),有缘再介绍