您当前的位置: 首页 > 

庄小焱

暂无认证

  • 3浏览

    0关注

    805博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

JDK源码——LockSupport类

庄小焱 发布时间:2021-11-25 20:57:59 ,浏览量:3

摘要

线程等待唤醒机制(wait/notify)。LockSupport中的park()和unpark()的作用分别是阻塞线程和解除阻塞线程。

synchronized和wait()/notify()方法
package com.zhuangxiaoyan;

/**
 * @Classname test1
 * @Description TODO
 * @Date 2021/11/25 19:43
 * @Created by xjl
 */
public class test1 {
    static Object objectlock = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            //synchronized (objectlock) {
                System.out.println(Thread.currentThread().getName() + "\t" + "----come in");
                try {
                    objectlock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "\t " + "----被唤醒");
            //}
        }, "A").start();

        new Thread(() -> {
            //synchronized (objectlock) {
                objectlock.notify();
                System.out.println(Thread.currentThread().getName() + "\t " + "----被唤醒");
            //}
        }, "B").start();
    }
}

0bject类中的wait、notify、notifyALL用于线程等待和唤醒的方法,都必须在synchronized内部执行必须用到关键字synchronized。先wait后notify才不会报错。

condition类 awit() 和signal()方法
package com.zhuangxiaoyan;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Classname test1
 * @Description TODO
 * @Date 2021/11/25 19:43
 * @Created by xjl
 */
public class test1 {
    static Object objectlock = new Object();
    static Lock lock=new ReentrantLock();
    static Condition condition=lock.newCondition();
    public static void main(String[] args) {
        new Thread(() -> {
                lock.lock();
                try {
                    System.out.println(Thread.currentThread().getName() + "\t" + "----come in");
                    try {
                        condition.await();
                    }catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "\t " + "----被唤醒");
                }finally {
                    lock.unlock();
                }
        }, "A").start();

        new Thread(() -> {
            lock.lock();
            try {
                condition.signal();
                System.out.println(Thread.currentThread().getName() + "\t " + "----被唤醒");
            } finally {
                lock.unlock();
            }

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

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

LockSupport类 park()和unpark()方法

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

package com.zhuangxiaoyan;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Classname test1
 * @Description TODO
 * @Date 2021/11/25 19:43
 * @Created by xjl
 */
public class test1 {

    public static void main(String[] args) {
        Runnable target;
        Thread a=new Thread(()->{
         try {
            TimeUnit.SECONDS.sleep(3L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
            System.out.println(Thread.currentThread().getName() + "\t" + "----come in");
            LockSupport.park();//被阻塞....等待通知等待放行,它要通过需要许可证
            System.out.println(Thread.currentThread().getName() + "\t " + "----被唤醒");
        },"a");
        a.start();
       
        Thread b=new Thread(()->{
            LockSupport.unpark(a);
            System.out.println(Thread.currentThread().getName() + "\t " + "----被唤醒a线程");
        });
        b.start();
    }
}

park和unpark是没有顺序的。

为什么可以先唤醒线程后阻塞线程?

因为unpark获得了一个凭证,之后再调用park方法,就可以名正言顺的凭证消费,故不会阻塞。

为什么唤醒两次后阻塞两次,但最终结果还会阻塞线程?

因为凭证的数量最多为1,连续调用两次unpark和调用一次unpark 效果一样,只会增加一个凭证;而调用两次park却需要消费两个凭证,证不够,不能放行。

关注
打赏
1657692713
查看更多评论
立即登录/注册

微信扫码登录

0.0431s