AQS背后的故事

248 阅读8分钟

“这是我参与更文挑战的第23天,活动详情查看: 更文挑战

LockSupport(锁支持):

是什么,能干嘛,去哪里下载,怎么玩;

四步走

来源
来源

LockSupport的本质:

就是用于线程等待唤醒机制的加强版本-->改良版本 其中有两个特别的方法;

  • park();
  • unPark();

就是wait()和notify()的方法;

其中object类来说, wait()是让线程等待,notify()将线程唤醒;

juc中 condition的await()让线程等待,使用signal()方法唤醒线程;

标准的实现,生产者和消费者的模型:

1.利用wait()和notify()方法-->synchronized的关键字,铁三角缺一不可:

package com.atguowang.thirdinterview.juc;

import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;

import java.util.concurrent.locks.LockSupport;

/**
 * @author lucas
 * @time 2020/10/27/10:29
 * @description 锁对象,是什么,能干嘛,从哪里下,怎么玩
 * AB学习法
 **/
public class TestLockSupport {
    //锁对象
    static Object data = new Object();

    public static void main(String[] args) {
        //打印
        //System.out.println(Thread.currentThread().getName()+"\t"+"正在运行的线程");

        new Thread(() -> {
            synchronized (data) {
                System.out.println(Thread.currentThread().getName() + "\t" + "---线程come in");
                try {
                    data.wait(); //等待操作

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "\t" + "被唤醒");
            }
        }, "A").start();


        //第二个线程开始唤醒;

        new Thread(() -> {
            synchronized (data) {
                data.notify();
                System.out.println(Thread.currentThread().getName() + "\t" + "通知");
            }

        }, "B").start();
    }
}

解析:

当线程新建进入的时候,come in ,然后经过wait方法,,只能等着被notify之后,才可以执行后面的代码,、 这里synchronized的锁对象是同一个,所以,其他的线程进入的时候可以直接,唤醒,也就是多个线程可以对可重入锁的(共同锁对象进行等待和唤醒)

异常情况1: 如果我们将synchronized直接删除掉,只是单纯的保留着wait和notify(),还可以正常工作吗?

不能进入wait;

Exception in thread "A" Exception in thread "B" java.lang.IllegalMonitorStateException

package com.atguowang.thirdinterview.juc;

import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;

import java.util.concurrent.locks.LockSupport;

/**
 * @author lucas
 * @time 2020/10/27/10:29
 * @description 锁对象,是什么,能干嘛,从哪里下,怎么玩
 * AB学习法
 **/
public class TestLockSupport {
    //锁对象
    static Object data = new Object();

    public static void main(String[] args) {
        //打印
        //System.out.println(Thread.currentThread().getName()+"\t"+"正在运行的线程");

        new Thread(() -> {
//            synchronized (data) {
                System.out.println(Thread.currentThread().getName() + "\t" + "---线程come in");
                try {
                    data.wait(); //等待操作

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "\t" + "被唤醒");
//            }
        }, "A").start();


        //第二个线程开始唤醒;

        new Thread(() -> {
//            synchronized (data) {
                data.notify();
                System.out.println(Thread.currentThread().getName() + "\t" + "通知");
//            }

        }, "B").start();
    }
}

第二种情况异常:

如果我们将线程wait->notify的方法调换,先唤醒然后等待,会有什么异常呢

这种可以使用先让等待线程睡三秒,优先去执行唤醒的线程,试一下;

package com.atguowang.thirdinterview.juc;

import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;

import java.sql.Time;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

/**
 * @author lucas
 * @time 2020/10/27/10:29
 * @description 锁对象,是什么,能干嘛,从哪里下,怎么玩
 * AB学习法
 **/
public class TestLockSupport {
    //锁对象
    static Object data = new Object();

    public static void main(String[] args) {


        new Thread(() -> {
            //暂停几秒钟
            try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }
            synchronized (data) {
                System.out.println(Thread.currentThread().getName() + "\t" + "---线程come in");
                try {
                    data.wait(); //等待操作
                } catch (InterruptedException e) {
                    e.printStackTrace(); }
                System.out.println(Thread.currentThread().getName() + "\t" + "被唤醒"); }
        }, "A").start();


        //第二个线程开始唤醒;

        new Thread(() -> {
            synchronized (data) {
                data.notify();
                System.out.println(Thread.currentThread().getName() + "\t" + "通知");
            }

        }, "B").start();
    }
}

表示的时候--铁三角不能打破,或者说; wait和notify的位置不能改变,如果说,一个线程中不能改变-->wait --->

package com.atguowang.thirdinterview.juc;

import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;

import java.sql.Time;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

/**
 * @author lucas
 * @time 2020/10/27/10:29
 * @description 锁对象,是什么,能干嘛,从哪里下,怎么玩
 * AB学习法
 **/
public class TestLockSupport {
    //锁对象
    static Object data = new Object();

    public static void main(String[] args) {


        new Thread(() -> {
            //暂停几秒钟
            //try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }
            synchronized (data) {
                System.out.println(Thread.currentThread().getName() + "\t" + "---线程come in");
                try { data.wait(); //等待操作
                      System.out.println("处于被等待的状态");
                      data.notify();
                        System.out.println("处于一个唤醒的状态");
                } catch (InterruptedException e) {
                    e.printStackTrace(); }
                System.out.println(Thread.currentThread().getName() + "\t" + "被唤醒"); }
        }, "A").start();


//        第二个线程开始唤醒;

        new Thread(() -> {
            synchronized (data) {
                data.notify();
                System.out.println(Thread.currentThread().getName() + "\t" + "通知");
            }

        }, "B").start();
    }
}

还得保证具体的数据,我们将线程的转化为具体的使用,方法是一个简单的过程,如果说一个对象我们可以得到;

ReentrantLock是java.util.concurrent.Locks.ReentrantLock的比较数据,然后我们将使用的过程直接变成具体的数据; 这个对于重入互斥锁,synchronized的扩展,

因为他有具体的condition的一个锁的状态--

ReentrantLock ----》代表的await()和具体的signal();

其中使用的await()等方式就是在利用状态(condition)是一个接口。里面有默认的方法和具体的唤醒--等待阻塞;

lock()-->sync.lock()---》AQS

AbstractQueuedSynchronizer --》AQS AbstractQueuedSychronzier 查看LockSupport的显示结果--可以成为具体的数据展示;

JUC-->AQS-->LockSupport

卢卡寄语

当前可重入锁的底层 AQS,在底层就是锁支持,所以对于锁来说, 分类搞懂以后,对于最底层的知识,以不变应万变才是做好的,

晚安啦,我是卢卡,看完记得点赞哦