前面文章末尾,我们提到wait会释放锁,而sleep不会释放锁。那么什么是锁,锁就是把线程锁住。也就是线程能被锁住,当然还有释放锁。这篇来了解下ReentrantLock类,中文的意思就是互斥锁。主要学习这个类的lock()获取锁和unlock()释放锁。
互斥锁代码举例
我们先来看代码,然后来解释。
package thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLock_Demo {
public static void main(String[] args) {
Printer3 p = new Printer3();
new Thread() {
public void run() {
while(true) {
try {
p.print1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread() {
public void run() {
while(true) {
try {
p.print2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread() {
public void run() {
while(true) {
try {
p.print3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
class Printer3 {
private int flag = 1;
private ReentrantLock r = new ReentrantLock();
private Condition c1 = r.newCondition();
private Condition c2 = r.newCondition();
private Condition c3 = r.newCondition();
public void print1() throws InterruptedException {
r.lock();
if(flag != 1) {
c1.await(); // C1进入等待状态
}
System.out.print("跟");
System.out.print("我");
System.out.print("一");
System.out.print("起");
System.out.println("念");
flag = 2;
c2.signal(); // c1等待 唤醒c2
r.unlock();
}
public void print2() throws InterruptedException {
r.lock();
if(flag != 2) {
c2.await();
}
System.out.print("做");
System.out.print("测");
System.out.print("试");
System.out.print("死");
System.out.print("路");
System.out.print("一");
System.out.println("条");
flag = 3;
c3.signal(); // c2等待,唤醒c3
r.unlock();
}
public void print3() throws InterruptedException {
r.lock();
if(flag != 3) {
c3.await();
}
System.out.print("信");
System.out.print("才");
System.out.print("怪");
System.out.println("呢");
flag = 1;
c1.signal(); // c3等待,唤醒c1
r.unlock();
}
}
运行结果和前面使用同步锁是一样的。第一点不同,由前面while语句改成了if语句判断。第二个不同,由互斥锁对象r调用lock和unlock方法来替代原来的synchronized。第三点不同,三个线程之间,唤醒都是很明确的,线程1等待唤醒的是线程2,线程2等待唤醒线程3,线程3等待唤醒的线程1. 这里使用了互斥锁的成员方法newCondition(),里面Condition类有await()方法就是相当于前面学习的wait方法,signal()方法就是前面的notify()方法。互斥锁比前面的同步代码块功能要强大很多。