LockSupport解读(java)

2023-12-17 09:41:53 浏览数 (1)

LockSupport基本介绍

LockSupport是JDK1.5中新增的一个类,用于实现线程的阻塞和唤醒。在Java并发编程中,线程的阻塞和唤醒是非常重要的操作,可以通过wait()和notify()方法来实现,但是它们有一定的局限性,比如只能阻塞和唤醒当前线程,并且必须要在synchronized块中执行。而LockSupport则可以弥补这些不足。

LockSupport中的park()和unpark()方法可以分别实现阻塞线程和唤醒线程的功能。和其他的线程控制方法相比,LockSupport有以下优点:

  1. 可以阻塞和唤醒指定的线程,而不是像wait()和notify()方法一样只能阻塞和唤醒当前线程。
  2. 不需要获取锁才能操作,而是将操作权限直接分配给调用线程。
  3. 唤醒操作可以先于阻塞操作,而不像wait()方法只能等待notify()方法的唤醒。

LockSupport使用了一种名为"许可证"(permit)的概念来做到阻塞和唤醒线程的功能,每个线程都有一个许可证。与Semaphore不同的是,许可证的累加上限是1。permit许可证默认没有不能放行,所以一开始调用park()方法当前线程就会阻塞,直到别的线程给当前线程的发放permit,park方法才会被唤醒。调用unpark(thread)方法后,就会将thread线程的许可证permit发放,会自动唤醒park线程,即之前阻塞中的LockSuppot.pak()方法会立即返回。

LockSupport和其他线程控制方法相比,有以下优势:

  • LockSupport可以在任意位置阻塞和唤醒线程,不需要在synchronized块中执行。
  • LockSupport可以阻塞和唤醒指定的线程,而不是像wait()和notify()方法一样只能阻塞和唤醒当前线程。
  • LockSupport不需要获取锁才能操作,而是将操作权限直接分配给调用线程。
  • LockSupport的唤醒操作可以先于阻塞操作,而不像wait()方法只能等待notify()方法的唤醒。
  • LockSupport没有死锁的风险,因为它不需要获取锁就可以进行阻塞和唤醒操作。

三种等待唤醒方式

方式1:Object中的wait()和notify()

代码:

代码语言:javascript复制
 class WaitNotifyDemo {

    public static void main(String[] args) {
        Object lock = new Object();
        Thread t1 = new Thread(() -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName()  "进入等待状态");
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()  "被唤醒,继续执行");
            }
        }, "线程1");

        Thread t2 = new Thread(() -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName()  "唤醒其他线程");
                lock.notify();
            }
        }, "线程2");

        t1.start();
        t2.start();
    }

}

描述:

wait()和notify()是Object类中的方法,用于实现线程之间的等待和唤醒。当一个线程调用了对象的wait()方法时,该线程会释放对象的锁,并进入等待状态,等待其他线程调用对象的notify()方法将它唤醒;而当一个线程调用了对象的notify()方法时,该对象会随机唤醒一个正在等待它的线程。

在上面的代码中,我们创建了一个共享对象lock,然后启动两个线程t1和t2。t1线程调用了lock的wait()方法进入等待状态,而t2线程调用了lock的notify()方法唤醒t1线程,使其继续执行。

方式2:JUC包中的Condition.await()和signal()

代码:

代码语言:javascript复制
 class ConditionDemo {

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

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName()  "进入等待状态");
                condition.await();
                System.out.println(Thread.currentThread().getName()  "被唤醒,继续执行");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "线程1");

        Thread t2 = new Thread(() -> {
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName()  "唤醒其他线程");
                condition.signal();
            } finally {
                lock.unlock();
            }
        }, "线程2");

        t1.start();
        t2.start();
    }
}

描述:

Condition是JUC(java.util.concurrent)包中的一个接口,用于实现线程之间的等待和唤醒。相比于Object的wait()和notify()方法,Condition提供了更加灵活的线程控制方式。

在上面的代码中,我们创建了一个共享锁对象lock和一个Condition对象condition。线程t1调用lock的lock()方法获取锁,并调用condition的await()方法进入等待状态;而线程t2调用lock的lock()方法获取锁,并调用condition的signal()方法唤醒线程t1,使其继续执行。

方式3:LockSupport类

代码:

代码语言:javascript复制
class LockSupportDemo {

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName()   "进入等待状态");
            LockSupport.park();
            System.out.println(Thread.currentThread().getName()   "被唤醒,继续执行");
        }, "线程1");
        t1.start();

        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Thread t2 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName()   "唤醒其他线程");
            LockSupport.unpark(t1);
        }, "线程2");
        t2.start();
    }
}

描述:

LockSupport是JDK1.5中新增的一个类,用于实现线程的阻塞和唤醒。在Java并发编程中,线程的阻塞和唤醒是非常重要的操作,可以通过wait()和notify()方法来实现,但是它们有一定的局限性,比如只能阻塞和唤醒当前线程,并且必须要在synchronized块中执行。而LockSupport则可以弥补这些不足。

在上面的代码中,我们创建了一个线程t1,它调用LockSupport的park()方法进入等待状态,而线程t2调用LockSupport的unpark()方法唤醒线程t1,使其继续执行。

0 人点赞