ReentrantLock主要是用来替代synchronized的。
先来看一个例子:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class o1reentrantlock {
public static void main(String [] args){
ReentrantLock lock = new ReentrantLock();
m5 a = new m5();
new Thread(() -> {
try {
lock.lock();
for(int i=0; i<5; i++){
a.m1();
System.out.println(Thread.currentThread().getName()+"执行了+1,结果为:"+a.count);
TimeUnit.SECONDS.sleep(1);
}
} catch (Exception e) {
// TODO: handle exception
} finally {
System.out.println("释放锁!");
lock.unlock();
}
},"t1").start();
new Thread(() -> {
try {
lock.lock();
for(int i=0; i<5; i++){
a.m1();
System.out.println(Thread.currentThread().getName()+"执行了+1,结果为:"+a.count);
TimeUnit.SECONDS.sleep(1);
}
} catch (Exception e) {
// TODO: handle exception
} finally {
lock.unlock();
}
},"t2").start();
}
}
class m5{
int count = 0;
void m1(){
this.count++;
}
}
程序执行结果为;
来说一下这段程序:
我们创建了一把 ReentrantLock 锁 ,第一个线程拿到锁后(lock),执行五次循环打印,finnaly里释放锁,然后第二个线程拿到锁后继续执行5次循环打印,最终释放锁。
ReentrantLock 不会自动释放锁,必须必须必须手动释放锁。
synchronized 出现异常会自动释放锁,ReentrantLock 遇到异常不会释放锁,需要在finnaly()块中释放锁。一定要注意,如果稍不注意就造成死锁了。
ReentrantLock 可以进行尝试锁定,如果锁定,那我就执行,如果没拿到锁,那我就该干嘛干嘛。(就是非阻塞),并且ReentrantLock 可以指定尝试锁定超时期限,如果在规定时间内我还没有获得锁,那么继续执行。
看代码:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class o1reentrantlock {
public static void main(String [] args){
m5 a = new m5();
new Thread(() -> {
for(int i=0; i<5; i++){
a.m1();
}
},"t1").start();
new Thread(() -> {
for(int i=0; i<5; i++){
a.m1();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
},"t2").start();
}
}
class m5{
int count = 0;
ReentrantLock lock = new ReentrantLock();
void m1(){
boolean islock = false;
try {
islock = lock.tryLock();
if(islock){
System.out.println(Thread.currentThread().getName()+"拿到锁了!");
this.count++;
System.out.println("当前count值为:"+this.count);
}else{
System.out.println(Thread.currentThread().getName()+"没拿到锁,算拉倒!");
}
} catch (Exception e) {
// TODO: handle exception
} finally {
if(islock) lock.unlock();
}
}
}
先说一下这段程序,两个线程。各调用m1方法5次,两个线程都尝试获取锁,如果没得到就输出“”算拉倒”,那最终count值+打印的“算拉倒”应该等于10;
ReentrantLock 可以对interrupt时间做出反应。
看代码:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class gongping {
public static void main(String [] args){
m a = new m();
new Thread(() -> {
for (int i =0; i<1000; i++){
a.m1();
}
}).start();
new Thread(() -> {
for (int i =0; i<1000; i++){
a.m1();
}
}).start();
}
}
class m{
ReentrantLock lock = new ReentrantLock();
void m1(){
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+"执行了操作!");
} catch (Exception e){
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
代码说明:两个线程各执行1000次打印输出。
输出很不规范,线程一一段线程二一段,而且两个线程执行时间也不同有的多有的少。(太长了,图就不贴了)
接下让我们改成公平锁执行一下
ReentrantLock lock = new ReentrantLock(true);
两个线程你一次我一次比较公平。