美文网首页
16、可重入锁和LockSurport

16、可重入锁和LockSurport

作者: i小雨 | 来源:发表于2021-03-03 11:35 被阅读0次
  • 定义:LockSurport是用来创建锁和其他同步类的基本线程阻塞原语
    LockSurport类使用了一种名为permit(许可)的概念来做阻塞和唤醒线程的功能,每个线程都有一个许可(permit)。permit只有0和1两个值,默认是0.
    可以把两个值0和1看成信号量(semaphore),但与semaphore不同的是,许可的累加上限是1.

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

  • 1、使用Object中的wait()方法让线程等待,使用Object中的notify()方法唤醒线程。
  • 2、使用JUC包中Condition的await()方法让线程等待,使用signal()方法唤醒线程。
  • 3、LockSurport类可以阻塞当前线程(park())以及唤醒指定被阻塞的线程(unpark())

使用wait和notify:

public class TestWaitAndNotify {
    static Object objectLock = new Object();
    
    public static void main(String[] args) {
        
        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(3); //暂停3秒为了让notify先执行,会导致wait的线程不能被唤醒
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            synchronized (objectLock) {
                System.out.println(Thread.currentThread().getName()+"---come in");
                try {
                    objectLock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"---被唤醒");
            }
        },"A").start();
        
        new Thread(()->{
            synchronized (objectLock) {
                objectLock.notify();;
                System.out.println(Thread.currentThread().getName()+"---通知");
            }
        },"B").start(); 
    }
}
*************结果***************
B---通知
A---come in
**********************分析:******************
1、wait(),notify(),notifyAll() 必须结合synchronized使用
2、先wait,后notify,否则wait的线程无法被唤醒。

使用await和signal

public class TestAwaitAndSignal {
    
    static Lock lock = new ReentrantLock();
    static Condition condition = lock.newCondition();
    
    public static void main(String[] args) {
        
        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName()+"---come in");
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"---被唤醒");
            } finally {
                lock.unlock();
            }
            
        },"A").start();
        
        new Thread(()->{
            lock.lock();
            try {
                condition.signal();
                System.out.println(Thread.currentThread().getName()+"----通知");
            } finally {
                lock.unlock();
            }
        },"B").start();
                
    }

}
*************结果***************
B---通知
A---come in
**********************分析:******************
1、await(),signal(),signalAll() 必须结合lock使用
2、先await,后signal,否则等待的线程无法被唤醒。

可以发现:synchronized和lock的等待唤醒必须先等待后唤醒,程序才能正常执行。

LockSurport

通过park()和unpark()实现阻塞和唤醒线程的操作。

public class TestLockSurport {
    
    public static void main(String[] args) {
        
        Thread a = new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            System.out.println(Thread.currentThread().getName()+"---come in");
            
            LockSupport.park();//被阻塞,等待通发放许可证permit
            
            System.out.println(Thread.currentThread().getName()+"---被唤醒");
        },"A");
        a.start();
        
        
        Thread b = new Thread(()->{
            LockSupport.unpark(a);
            System.out.println(Thread.currentThread().getName()+"---通知");
        },"B");
        b.start();      
    }
}
******************结果:*******************
B---通知
A---come in
A---被唤醒
**********************分析:******************
1、可以看到先通知后等待,也会唤醒等待的线程。
图片.png

当调用park方法时

  • 如果有凭证,则会直接消耗掉这个凭证然后正常退出;
  • 如果无凭证,就必须阻塞等待凭证可用。

unpark则相反
它会增加一个凭证,但凭证最多只能有1个,累加无效。

相关文章

  • 16、可重入锁和LockSurport

    定义:LockSurport是用来创建锁和其他同步类的基本线程阻塞原语LockSurport类使用了一种名为per...

  • Java 可重入锁 公平锁 读写锁

    1.可重入锁 如果锁具备可重入性,则称作为可重入锁。 像synchronized和ReentrantLock都是可...

  • 可重入锁和非可重入锁

    1 可重入锁 (ReentrantLock和synchronized)可重入锁指的是可重复可递归调用的锁,在外层使...

  • J.U.C-AQS-ReentrantLock

    ReentrantLock(可重入锁)和synchronized区别 可重入性 锁的实现(ReentrantLoc...

  • Java中的各种锁

    一个线程中的多个流程能不能获取同一把锁:可重入锁和非可重入锁 可重入锁 可重入性:表明了锁的分配机制,是基于线程的...

  • 可重入锁和非可重入锁

    1.是个What 可重入锁,也叫做递归锁,指的是同一个线程T在进入外层函数A获得锁L之后,T继续进入内层递归函数B...

  • ReentrantLock 源码分析

    锁的基本概念 可重入锁 Reentrant 就是可重入的意思,如果锁具备可重入性,则称作为可重入锁。像synchr...

  • 不可重入锁和可重入锁

    这个方法在下面的一个场景里面执行不会有问题,都可以很好的处理两个业务对同一个号码互斥执行的需求,如果两个方法并发执...

  • 可重入锁和不可重入锁

    不可重入锁 先来设计一种锁 这其实是个不可重入锁,举个例子 当调用print()方法时,获得了锁,这时就无法再调用...

  • 不可重入锁和可重入锁

    所谓不可重入锁,即若当前线程执行某个方法已经获取了该锁,那么在方法中尝试再次获取锁时,就会获取不到被阻塞; 所谓可...

网友评论

      本文标题:16、可重入锁和LockSurport

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