it编程 > 编程语言 > C/C++

多线程-lock与lockInterruptibly的区别及说明

16人参与 2025-02-27 C/C++

多线程lock与lockinterruptibly区别

在多线程编程中,锁(lock)是用来确保多个线程在访问共享资源时能够保持一致性和正确性的关键工具。

java 提供了多种实现锁的机制,其中最常用的是 reentrantlockreentrantlock 提供了两种获取锁的方法:locklockinterruptibly

这两者在处理线程中断时表现不同,理解这些差异对于编写健壮的多线程程序至关重要。

lock 方法

示例代码:

public static void lock() {
    lock lock = new reentrantlock();
    try {
        lock.lock();
        thread t1 = new thread(() -> {
            thread currentthread = thread.currentthread();
            try {
                lock.lock();
                system.out.println(currentthread.getname() + " lock后的代码");
            } finally {
                lock.unlock();
            }
            system.out.println("currentthread = " + currentthread.getname() + " isinterrupted:" + currentthread.isinterrupted());
        }, "t1");
        t1.start();
        t1.interrupt();
        system.out.println("currentthread = " + thread.currentthread().getname());
    } finally {
        lock.unlock();
    }
}

执行结果:

currentthread = main
t1 lock后的代码
currentthread = t1 isinterrupted:true

解释:

在这个示例中,主线程(main)首先获取了锁。然后启动一个新线程(t1),该线程尝试再次获取同一个锁。主线程在启动 t1 后立即调用 t1.interrupt() 方法中断 t1 线程。

尽管 t1 线程被中断,它还是成功获取到了锁并执行了锁后的代码。这是因为 lock 方法在获取锁时不会理会线程的中断状态,只要锁可用,它就会获取锁。换句话说,即使线程被中断,它也会继续等待获取锁,直到成功为止。

lockinterruptibly 方法

示例代码:

public static void lockinterruptiblydemo() {
    lock lock = new reentrantlock();
    try {
        lock.lock();
        thread t1 = new thread(() -> {
            thread currentthread = thread.currentthread();
            try {
                lock.lockinterruptibly();
                system.out.println(currentthread.getname() + " lockinterruptibly后的代码");
            } catch (interruptedexception e) {
                e.printstacktrace();
            } finally {
                lock.unlock();
            }
            system.out.println("currentthread = " + currentthread.getname() + " isinterrupted:" + currentthread.isinterrupted());
        }, "t1");
        t1.start();
        t1.interrupt();
        system.out.println("currentthread = " + thread.currentthread().getname());
    } finally {
        lock.unlock();
    }
}

执行结果:

currentthread = main
java.lang.interruptedexception
    at java.util.concurrent.locks.abstractqueuedsynchronizer.acquireinterruptibly(abstractqueuedsynchronizer.java:1220)
    at java.util.concurrent.locks.reentrantlock.lockinterruptibly(reentrantlock.java:335)
    at xxx.lambda$lockinterruptiblydemo$1(xxx.java:39)
    at java.lang.thread.run(thread.java:748)
exception in thread "t1" java.lang.illegalmonitorstateexception
    at java.util.concurrent.locks.reentrantlock$sync.tryrelease(reentrantlock.java:151)
    at java.util.concurrent.locks.abstractqueuedsynchronizer.release(abstractqueuedsynchronizer.java:1261)
    at java.util.concurrent.locks.reentrantlock.unlock(reentrantlock.java:457)
    at xxx.lambda$lockinterruptiblydemo$1(xxx.java:44)
    at java.lang.thread.run(thread.java:748)

解释:

在这个示例中,t1 线程尝试获取锁时调用了 lockinterruptibly 方法。与 lock 方法不同,lockinterruptibly 在尝试获取锁时会检查线程的中断状态。如果线程被中断,它会立即抛出 interruptedexception 异常,而不会继续等待获取锁。

执行结果显示,t1 线程在尝试获取锁时被中断,并且抛出了 interruptedexception。由于异常被捕获并打印,t1 线程并没有获取锁,这避免了在某些情况下可能出现的死锁问题。

区别总结

中断响应

使用场景

面试题:为什么 aqs 中的队列设计为双向链表?

aqs(abstractqueuedsynchronizer)是 java 并发包中锁和同步器的基础框架。aqs 内部使用了一个 fifo(先进先出)的双向链表来管理等待线程的队列。

原因:

双向遍历

节点删除

状态更新

实现复杂性

通过这种设计,aqs 能够更高效地管理线程队列,确保锁和同步器的高性能和正确性。

详细分析:aqs 中的双向链表

aqs 是一个基于节点的框架,所有等待获取锁的线程都会被封装成一个节点并加入到等待队列中。该队列的结构和操作直接影响锁的性能和响应能力。

aqs 中的主要节点结构:

每个节点包含以下主要部分:

操作示例:

入队

出队

状态传播

总结

理解 locklockinterruptibly 的区别有助于我们在多线程编程中选择适当的锁获取方式,确保程序的健壮性和响应能力。而 aqs 中的双向链表设计则是确保锁和同步器高效管理等待线程队列的重要基础,这种设计使得线程管理更加高效和灵活,在高并发场景中表现尤为突出。通过深入理解这些底层机制,我们可以更好地编写高性能的多线程应用程序。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

Qt Creator + CMake 构建教程的方法步骤

02-27

C++中pair使用的示例代码

02-26

解读为什么@Autowired在属性上被警告,在setter方法上不被警告问题

02-28

C++中BitSet和Bloom_Filter的实现

02-28

深入理解Qt 初始项目代码

02-28

Qt 中集成mqtt协议的使用方法

02-24

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论