zoukankan      html  css  js  c++  java
  • 可重入锁和LockSupport相关

    代码块方式

    public class ReEnterLockDemo {
        static Object objectLockA = new Object();
    
        public static void m1() {
            new Thread(() -> {
                synchronized (objectLockA) {
                    System.out.println(Thread.currentThread().getName() + "	" + "---外层调用");
                    synchronized (objectLockA) {
                        System.out.println(Thread.currentThread().getName() + "	" + "---外层调用");
                        synchronized (objectLockA) {
                            System.out.println(Thread.currentThread().getName() + "	" + "---外层调用");
                        }
                    }
                }
            },"t1").start();
        }
    
    
        public static void main(String[ ]args ) {
            m1();
        }
    }

    代码方法:

    public class ReEnterLockDemo1 {
    
    
        public synchronized  void m1(){
            System.out.println("----外层");
            m2();
        }
    
        public synchronized  void m2(){
            System.out.println("----中层");
            m3();
        }
    
        public synchronized  void m3(){
            System.out.println("----内层");
    
        }
        public static void main(String args[]) {
            ReEnterLockDemo1 reEnterLockDemo1 = new ReEnterLockDemo1();
            reEnterLockDemo1.m1();
        }
    }

    wait 和notify

    public class LockSupportDemo {
        static Object objectLock = new Object();
        public static void main(String[] args) {
            new Thread( () -> {
                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) {
                    System.out.println(Thread.currentThread().getName() +"	" +"----被通知");
    
                    try {
                        objectLock.notify();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },"B").start();
        }
    }


    结论:1.wait方法和notify方法,两个都需要同步代码块,否则会抛异常
       2. 将notify放在wait方法前面,程序无法执行,无法唤醒

    lock 实例

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

    LockSupport的支持用法

    public class LockSupportDemo2 {
    
        public static void main(String[] args) {
            Thread a = new Thread( () -> {
    
                System.out.println(Thread.currentThread().getName() +"	" +"----come in");
                LockSupport.park();
                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();
        }
    }

     结论:

    LockSupport调用的Unsafe中的native代码

    LockSupport提供park() 和unpark()方法实现阻塞线程和解除线程阻塞的过程。

    LockSupport和每个使用它的线程独有一个许可(permit)关联,permit相当于1,0的开关,默认是0。

    调用一次unpark就加1变成1,调用一次park会消费permit,也就是将1变成0,同时park立即返回。

    如再次调用park会变成阻塞(因为permit为零了会阻塞在这里,一直到permit变成1),这时调用unpark

    会把permit置为1.

    每个线程都有一个相关的permit,permit最多只有1个,重复调用unpark也不会阻塞凭证

    形象的理解
    线程阻塞需要消耗凭证(permit),这个凭证最多只有1个

    当调用park方法时

    如果有凭证,则会直接消耗掉这个凭证然后正常退出,

    如果无凭证就必须阻塞等待凭证可用。

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

    面试题:

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

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

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

    因为凭证的数量最多为1,连续调用两次unpark和调用一次unpark效果一样,只会增加一个凭证,

    而调用两次park却需要消费两个凭证,证不够,不能放行。

    --摘自 周阳老师

  • 相关阅读:
    Tensorflow io demo (待)
    tf.Dataset
    tf.estimator
    并发队列
    Callable的Future模式
    hadoop之HDFS介绍
    线程池
    并发工具类
    并发编程
    初学hadoop之hadoop集群搭建
  • 原文地址:https://www.cnblogs.com/liuyi13535496566/p/14433448.html
Copyright © 2011-2022 走看看