1.Reentrantlock 基本使用
reentrantlock 用于替代 synchronized,需要注意的是,必须要必须要必须要手动释放锁(重要的事情说三遍)
PS:使用syn锁定的话如果遇到异常,jvm会自动释放锁,但是lock必须手动释放锁,因此经常在finally中进行锁的释放
public class ReentrantLock1 {
ReentrantLock lock = new ReentrantLock();
void m1(){
lock.lock();
for(int i=0;i<10;i++)
System.out.println(i);
lock.unlock();
}
void m2(){
lock.lock();
try {
System.out.println("m2 Start!");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
ReentrantLock1 reentrantLock1 = new ReentrantLock1();
new Thread(()->reentrantLock1.m1()).start();
new Thread(()->reentrantLock1.m2()).start();
}
}
2.公平锁
ReentrantLock 还可以指定为公平锁
public class ReentrantLock2 {
// 参数为true表示为公平锁,请对比输出结果
ReentrantLock lock = new ReentrantLock(true);
void m1(){
for(int i = 0;i<100;i++){
this.lock.lock();
System.out.println(Thread.currentThread().getName()+"获得锁。。");
lock.unlock();
}
}
public static void main(String[] args) {
ReentrantLock2 reentrantLock2 = new ReentrantLock2();
new Thread(()->reentrantLock2.m1(),"t1").start();
new Thread(()->reentrantLock2.m1(),"t2").start();
}
}
3.tryLock
使用 reentrantlock 可以进行“尝试锁定” tryLock,这样无法锁定,或者在指定时间内无法锁定,线程可以决定是否继续等待。
使用 tryLock 进行尝试锁定,不管锁定与否,方法都将继续执行,可以根据 tryLock 的返回值来判定是否锁定。也可以指定 tryLock 的时间,由于 tryLock(time) 抛出异常,所以要注意 unclock 的处理,必须放到 finally 中。
public class ReentrantLock3 {
ReentrantLock lock = new ReentrantLock();
void m1(){
this.lock.lock();
try {
System.out.println("m1 start...");
TimeUnit.SECONDS.sleep(5);
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("别急m1完了。。");
this.lock.unlock();
}
}
void m2(){
boolean lock = false;
try {
lock = this.lock.tryLock(3, TimeUnit.SECONDS);
System.out.println(Thread.currentThread().getName()+"拿到锁了。");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
if(lock){
this.lock.unlock();
}
System.out.println("m2不等了!!!");
}
}
public static void main(String[] args) {
ReentrantLock3 reentrantLock3 = new ReentrantLock2();
new Thread(()->reentrantLock3.m1()).start();
new Thread(()->reentrantLock3.m2()).start();
new Thread(()->{
for(int i=1;i<=5;i++){
try {
TimeUnit.SECONDS.sleep(1);
System.out.println(i+"s");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
4.lockInterruptibly
使用 ReentrantLock 还可以调用 lockInterruptibly 方法,可以对线程 interrupt 方法做出响应。在一个线程等待锁的过程中,可以被打断
public class ReentrantLock4 {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
new Thread(()->{
try {
lock.lock();
System.out.println("t1 start...");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t1 stop");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
},"t1").start();
Thread t2 = new Thread(()->{
System.out.println("t2想要拿锁!");
try {
lock.lockInterruptibly();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println("鸭,没拿到锁。。。不要了!!!");
if(!lock.isLocked()){
lock.unlock();
}
}
},"t2");
t2.start();
for(int i=0;i<5;i++){
System.out.println(i+1+"...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(i == 2){
t2.interrupt();
}
}
}
}