程序员

java基础之互斥锁初解

2018-06-12  本文已影响3人  沈默的头号狗腿

  JDK中常用synchronized用于解决线程安全的问题,那么在JDK1.5的新特性中还提供了一个ReenTrantLock类用于解决线程安全问题,这个类就被称作为互斥锁。

假定我们有三个子线程协同执行任务,那么我们该如何来使用这个互斥锁呢

首先,我们需要建立一个ReenTrantLock对象

//创建互斥锁对象

static ReentrantLock r1 = new ReentrantLock();

既然有三个子线程,那么我们需要提供三个Condition对象,关于这个对象,我们在这里不过多深入,只需要知道Condition对象可以对当前线程执行一些改变线程状态的操作即可,下文会讲到有哪些操作。

//创建3个Condition

static Condition condition1 = r1.newCondition();

static Condition condition2 = r1.newCondition();

static Condition condition3 = r1.newCondition();

到了这一步,准备工作就做好了,我们可以开始创建三个子线程以及他们所执行的方法了

public static void main(String[] args) {

//线程1

new Thread(new Runnable() {

public void run() { try {

//测试方法1

text1();

} catch (Exception e) {

e.printStackTrace();

}}}).start();

//线程2

new Thread(new Runnable() {

public void run() {try {

//测试方法2

text2();

} catch (Exception e) {

e.printStackTrace();

}}}).start();

//线程3

new Thread(new Runnable() {

public void run() {try {

//测试方法3

text3();

} catch (Exception e) {

e.printStackTrace();

}}}).start();

}

测试方法如下

public static void text1() throws Exception {

r1.lock(); //加锁

System.out.println("text1");

Thread.sleep(1000);

condition1.await(); //让当前线程等待,且当前线程会带上condition1的标识,该标识可用来通过condition1唤醒线程,即进入阻塞状态

System.out.println("text1唤醒后");

condition2.signal(); //唤醒标识为condition2的阻塞状态的线程

r1.unlock(); //解锁

}

public static void text2() throws Exception {

r1.lock();

System.out.println("text2");

Thread.sleep(1000);

condition2.await(); //让当前线程等待,且当前线程会带上condition2的标识,该标识可用来通过condition2唤醒线程,即进入阻塞状态

System.out.println("text2唤醒后");

condition3.signal(); //唤醒标识为condition3的阻塞状态的线程

r1.unlock();

}

public static void text3() throws Exception {

r1.lock();

System.out.println("text3");

Thread.sleep(1000);

condition1.signal(); //唤醒标识为condition1的阻塞状态的线程

condition3.await(); //让当前线程等待,且当前线程会带上condition3的标识,该标识可用来通过condition3唤醒线程,即进入阻塞状态

System.out.println("text3唤醒后");

r1.unlock();

}

从上面的代码中我们可以看到,

其一,位于lock()unlock()方法之间的代码既是同步代码部分。

其二,ReenTrantLock的对象r1的lock()方法可以开启互斥锁,并且该锁的状态由r1来维护,即r1开启的锁只能由r1来解锁。

其三,Condition对象可以通过await()方法将当前线程设为阻塞状态,同时会解开锁,并且被设为阻塞状态的线程会被带上condition对象标识,当执行condition对象 . signal()来唤醒线程时,就会根据对象标识来选择唤醒哪个线程。

其四,ReenTrantLock的unlock()方法用来解锁

最终运行结果是

text1

text2

text3

text1唤醒后

text2唤醒后

text3唤醒后

通过结果可以看到,三个线程实现了协同工作。

本次互斥锁的讲解到此为止,目前的讲解还只停留在表面,有兴趣的朋友可以自己去深入了解下。

上一篇下一篇

猜你喜欢

热点阅读