LockSupport

LockSupport

LockSupport是什么

java.util.concurrent.locks下的一个类 LockSuport

LockSupport是用来创建锁和其他同步类的基本线程阻塞原语
LockSupport中的park()和unpark()的作用分别是阻塞线程和解除阻塞线程

线程等待唤醒机制(wait/notify)

三种让线程等待和唤醒的方法

方式一:使用Object中的wait()方法让线程等待,使用Object中的notify()方法唤醒线程
方式二:使用JUC包中的Condition的await()方法让线程等待,使用signal()方法唤醒线程
方式三:LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程

Object类中的wait和notify方法实现线程等待和唤醒

代码

正常

public class WaitNotifyDemo {
    static Object objectLock = new Object();

    public static void main(String[] args) {
        new Thread(()->{
            synchronized (objectLock){
                System.out.println("come in");
                try {
                    objectLock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("解锁");
            }
        },"AAA").start();

        new Thread(()->{
            synchronized (objectLock){
                System.out.println("----");
                objectLock.notify();
            }
        },"BBB").start();
    }
}

异常1

wait 和notify方法必须要在同步代码块或者方法里面且成对出现使用
否则,

Exception in thread "AAA" Exception in thread "BBB" java.lang.IllegalMonitorStateException
	at java.lang.Object.notify(Native Method)
	at com.zhj.test.WaitNotifyDemo.lambda$main$1(WaitNotifyDemo.java:22)
	at java.lang.Thread.run(Thread.java:750)
java.lang.IllegalMonitorStateException
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)
	at com.zhj.test.WaitNotifyDemo.lambda$main$0(WaitNotifyDemo.java:11)
	at java.lang.Thread.run(Thread.java:750)

异常2

将notify放在wait方法之前
程序无法执行,无法唤醒

总结

  1. wait和notify方法必须要要在同步代码块或者方法里面且成对出现使用
  2. 先wait后notify才ok

Condition接口中的await和signal方法实现线程的等待和唤醒

demo

public class ConditionWaitDemo {
    static ReentrantLock lock = new ReentrantLock();
    static Condition condition = lock.newCondition();
    public static void main(String[] args) {
        new Thread(()->{
            lock.lock();
            try {
                System.out.println("come in ");
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                System.out.println("解锁");
                lock.unlock();
            }
        },"AAA").start();

        new Thread(()->{
            lock.lock();
            try {
                System.out.println("---");
                condition.signal();
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        },"BBB").start();
    }
}

异常 与 synchronized 相同

传统的synchronized和lock实现等待唤醒通知的约束

  • 线程先要获得并持有锁,必须在锁块(synchronized或lock)中
  • 必须要 先等待后唤醒,线程才能够被唤醒

LockSupport类中的park等待和唤醒

是什么

LockSupport是用来创建锁和其他同步类的基本线程阻塞原语
LockSupport类使用了一种名为permit(许可)
的概念做到阻塞和唤醒线程的功能,每个线程都有一个许可(permit),permit只有两个值1和0,默认是0
可以把许可看成(0,1)信号量(Semaphore),但与Semaphore不同的是,许可的累加上限是1

方法
  • 阻塞

park/park(Object blocker)
阻塞当前线程/阻塞传入的具体线程

  • 唤醒

unpark(Thread thread)
唤醒处于阻塞状态的线程

demo
public class LockSupportDemo {
    public static void main(String[] args) {
        Thread a = new Thread(() -> {
            System.out.println("come in");
            LockSupport.park();
            System.out.println("解锁");
        }, "AAA");
        a.start();

        Thread bbb = new Thread(() -> {
            System.out.println("----");
            LockSupport.unpark(a);
        }, "BBB");
        bbb.start();
    }
}

解决问题:
不受锁块的影响
可以先唤醒后等待

重要说明

LockSupport是用来创建锁和其他同步类的基本线程阻塞原语
LockSupport是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,阻塞之后也有对应的唤醒方法。归根结底,LockSupport调用的Unsafe中的native代码
LockSupport提供的park()和unpark()方法实现阻塞线程和解除线程阻塞的过程
LockSupport和每个使用他的线程都有一个许可关联。permit 相当于1或0的开关,默认是0

形象的理解
线程阻塞需要消耗凭证(permit),这个凭证最多只有一个
当调用park方法时

  • 如果有凭证,则会直接消耗这个凭证然后正常退出
  • 如果无凭证,就会阻塞等待凭证可用
    连续两次调用park会阻塞
    而unpark则相反
    他会增加一个凭证,但凭证最多只能有1个,累加无效
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值