LockSupport面试题

在这里插入图片描述

1.synchronized–wait–notify

package com.fp.coupon.rest.facade;

public class Test {

  static Object object = new Object();

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

    new Thread(() -> {

      synchronized (object) {
        System.out.println(Thread.currentThread().getName() + "通知");
        object.notify();
      }
    }, "B").start();
  }
}

在这里插入图片描述

1.1不加锁执行
public class Test {

  static Object object = new Object();

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

    new Thread(() -> {

//      synchronized (object){
      System.out.println(Thread.currentThread().getName() + "通知");
      object.notify();
//      }
    }, "B").start();
  }
}

在这里插入图片描述

1.2修改执行顺序
public class Test {

  static Object object = new Object();

  public static void main (String[] args) {
    new Thread(() -> {
      try {
        TimeUnit.SECONDS.sleep(3);
      } catch (InterruptedException e) {
      }
      
      synchronized (object) {
        System.out.println(Thread.currentThread().getName() + "coming in");
        try {
          object.wait();
          System.out.println(Thread.currentThread().getName() + "被唤醒");
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }, "A").start();

    new Thread(() -> {

      synchronized (object) {
        System.out.println(Thread.currentThread().getName() + "通知");
        object.notify();
      }
    }, "B").start();
  }
}
  1. 线程B休息3秒,线程A正常被唤醒
  2. 线程A休息3秒,线程B coming in方法正常执行,但是不会被唤醒!
    在这里插入图片描述

2.lock–await–signal

public class Test {

  static ReentrantLock lock = new ReentrantLock();
  static Condition condition = lock.newCondition();


  public static void main (String[] args) {
    new Thread(() -> {

      try {
        lock.lock();
        System.out.println(Thread.currentThread().getName() + "coming in");
        condition.await();
        System.out.println(Thread.currentThread().getName() + "被唤醒");

      } catch (InterruptedException e) {
        e.printStackTrace();
      } finally {
        lock.unlock();
      }


    }, "A").start();

    new Thread(() -> {
      try {
        lock.lock();
        condition.signal();
        System.out.println(Thread.currentThread().getName() + "通知");

      } finally {
        lock.unlock();
      }

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

在这里插入图片描述

2.1不加锁执行
package com.fp.coupon.rest.facade;

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


public class Test {

  static ReentrantLock lock = new ReentrantLock();
  static Condition condition = lock.newCondition();


  public static void main (String[] args) {
    new Thread(() -> {

      try {
//        lock.lock();
        System.out.println(Thread.currentThread().getName() + "coming in");
        condition.await();
        System.out.println(Thread.currentThread().getName() + "被唤醒");

      } catch (InterruptedException e) {
        e.printStackTrace();
      } finally {
//        lock.unlock();
      }


    }, "A").start();

    new Thread(() -> {
      try {
//        lock.lock();
        condition.signal();
        System.out.println(Thread.currentThread().getName() + "通知");

      } finally {
//        lock.unlock();
      }

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

在这里插入图片描述

2.2修改执行顺序
public class Test {

  static ReentrantLock lock = new ReentrantLock();
  static Condition condition = lock.newCondition();


  public static void main (String[] args) {
    new Thread(() -> {

      try {
        TimeUnit.SECONDS.sleep(3);
        lock.lock();
        System.out.println(Thread.currentThread().getName() + "coming in");
        condition.await();
        System.out.println(Thread.currentThread().getName() + "被唤醒");

      } catch (InterruptedException e) {
        e.printStackTrace();
      } finally {
        lock.unlock();
      }


    }, "A").start();

    new Thread(() -> {
      try {
//        TimeUnit.SECONDS.sleep(3);
        lock.lock();
        condition.signal();
        System.out.println(Thread.currentThread().getName() + "通知");

      } catch (Exception e) {
        e.printStackTrace();
      } finally {
        lock.unlock();
      }

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

  1. 线程B休息3秒,线程A正常被唤醒
  2. 线程A休息3秒,线程B coming in方法正常执行,但是不会被唤醒!
    在这里插入图片描述

3.LockSupport

public class Test {

  public static void main (String[] args) {
    Thread a = new Thread(() -> {

      try {
        System.out.println(Thread.currentThread().getName() + "coming in");
        LockSupport.park();//被阻塞,等待唤醒
        System.out.println(Thread.currentThread().getName() + "被唤醒");

      } catch (Exception e) {
        e.printStackTrace();
      }
    }, "A");
    a.start();


    Thread b = new Thread(() -> {
      try {
        System.out.println(Thread.currentThread().getName() + "通知");
        LockSupport.unpark(a);//唤醒线程a

      } catch (Exception e) {
        e.printStackTrace();
      }
    }, "B");
    b.start();
  }
}
3.1修改执行顺序
public class Test {

  public static void main (String[] args) {
    Thread a = new Thread(() -> {

      try {
        TimeUnit.SECONDS.sleep(3);
        System.out.println(Thread.currentThread().getName() + "coming in");
        LockSupport.park();
        System.out.println(Thread.currentThread().getName() + "被唤醒");

      } catch (Exception e) {
        e.printStackTrace();
      }
    }, "A");
    a.start();


    Thread b = new Thread(() -> {
      try {
//        TimeUnit.SECONDS.sleep(3);
        System.out.println(Thread.currentThread().getName() + "通知");
        LockSupport.unpark(a);

      } catch (Exception e) {
        e.printStackTrace();
      }
    }, "B");
    b.start();
  }
}
  1. 线程B休息3秒,线程A正常被唤醒
  2. 线程A休息3秒,线程B coming in方法正常执行,可以被唤醒!
3.2是什么

LockSupport是用来创建锁和其他同步类的基本线程阻塞原语。
LockSupport是一个线程阻塞工具类,所有的方法都是静态的,可以让线程在任意位置阻塞,阻塞后也有相应的唤醒方法。

3.3使用

提供park()和unpark () 方法实现阻塞线程和接触线程阻塞。
每个线程都有一个许可(permit)关联,permit相当于1,0的开关,默认是0;
调用一次unpark就➕1变成1;
调用一次park就会消费permit,也就是变成0,同时park立即返回。

如果再次调用park会变成阻塞(因为permit=0的时候会阻塞,一直等到permit变成1),这时候需要调用unpark会把permit置为1

3.4面试题

为什么可以先唤醒线程后阻塞线程?
因为unpark获得了一个凭证,只有在调用park方法,就可以名正言顺的消费凭证,因此不会被阻塞。
为什么唤醒两次后阻塞两次,最终结果还是阻塞线程?
因为凭证的数量最多为1,两次unpark和一次unpark的结果是一样的,只会增加一个凭证;
调用两次park却需要消费两个凭证,证不够,不能放行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值