美文网首页程序员
java基础之互斥锁初解

java基础之互斥锁初解

作者: 沈默的头号狗腿 | 来源:发表于2018-06-12 08:07 被阅读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唤醒后

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

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

    相关文章

      网友评论

        本文标题:java基础之互斥锁初解

        本文链接:https://www.haomeiwen.com/subject/cgsheftx.html