如何保证加锁顺序以避免死锁?

2024-04-16

假设有以下 Account 类的两个对象 - account1 和 account2。并且有两个线程T1和T2。

T1 正在将金额 100 从账户 1 转移到账户 2,如下所示:

account1.transfer(account2, 100);

同样,T2 将金额 50 从 account2 转移到 account1:

account2.transfer(account1, 50);

Transfer() 方法显然容易出现死锁,因为两个线程 T1 和 T2 会尝试以相反的顺序获取锁。 (线程 T1 将首先尝试获取 account1 上的锁,然后再获取 account2 上的锁。而线程 T2 将尝试获取 account2 上的锁,然后再获取 account1 上的锁。)

(在这种情况下)确保始终保证锁定顺序的最佳方法是什么?

public class Account {
    private float balance;

    public class Account() {
        balance = 5000f;
    }

    private void credit(float amt) {
        balance += amt;
    }

    // To exclude noise assume the balance will never be negative
    private void debit(float amt) {
        balance -= amt;
    }

    // Deadlock prone as the locking order is not guaranteed
    public void transfer(Account acc2, float amt) {
        synchronized(this) {
            synchronized(acc2) {
                acc2.debit(amt);
                this.credit(amt);
            }
        }
    }
}

我只允许一个线程访问“帐户”数据。任何其他想要转移资金的线程都必须将一个“transferRequest”对象排队到其中,该对象包含帐户 ID、要转移的金额、异常/错误消息字段和回调/事件,并以 TransferRequest 作为线程的参数当它尝试事务时调用。

然后,传输将被完整序列化,唯一的锁位于队列中,因此不可能出现死锁。

我讨厌多把锁,无论顺序是否正确。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何保证加锁顺序以避免死锁? 的相关文章

  • 何时在多线程中使用 易失性?

    如果有两个线程访问全局变量 那么许多教程都说使该变量成为易失性的 以防止编译器将变量缓存在寄存器中 从而无法正确更新 然而 两个线程都访问共享变量需要通过互斥体进行保护 不是吗 但在这种情况下 在线程锁定和释放互斥体之间 代码位于关键部分
  • Objective-C中如何使用后台线程?

    我试图在按下按钮时运行 while 循环 但无法按下按钮 因为 while 循环会阻塞 UI 是否有一个后台线程 我可以在其中运行 while 循环并推送UIButton 就个人而言 我会在 UI 顶部运行 HUD 活动指示器 然后在后台运
  • 如何在 bash 脚本中使用并行编程/多线程?

    这是我的脚本 bin bash script to loop through directories to merge fastq files sourcedir path to source destdir path to dest fo
  • 在使用 stop_token 等待条件变量_any 时是否需要拥有锁来请求停止?

    在等待条件变量时 更改谓词状态的线程必须拥有锁 因此在唤醒期间不会错过更新 根据文档 这是必要的 即使在使用原子变量时也是如此 不过我不确定是否request stop 已经正确处理了 那么问题是 这两个选项中哪一个是正确且符合标准的呢 j
  • Awaiter (GetAwaiter) 和ContinueWith 有什么区别

    在 net 4 0中 我经常使用Task ContinueWith 但是之后我发现了 task GetAwaiter https stackoverflow com a 14171923 284758这似乎有同样的目的 有什么不同 如果您的
  • 发布/订阅架构

    我尝试编写一个发布 订阅系统 客户端和服务器端 其中客户端接收定期更新 如心跳 消息控制 并可以向服务器发出命令 订阅某些源 这样做的好方法是什么 我已经有一个实现线程池的服务器来管理传入的客户端连接 我想知道如何处理连接双方都可以在 Ne
  • 为什么将 volatile 与同步块一起使用?

    我在java中看到了一些示例 其中他们在代码块上进行同步以更改某些变量 而该变量最初被声明为易失性 我在单例类的示例中看到 他们将唯一实例声明为易失性 并且同步了该块初始化该实例 我的问题是为什么我们在同步它时声明它是易失性的 为什么我们需
  • 原子变量能保证内存可见性吗?

    关于内存可见性的小问题 代码示例1 class CustomLock private boolean locked false public boolean lock if locked locked true return true re
  • 具有阻塞功能的 Twisted LoopingCall

    我有一个应用程序需要轮询数据库以了解可能的配置更改 该应用程序是一个使用 Twisted 的简单 xmlrpc 服务器 我尝试过使用Twisted的LoopingCall来执行轮询 但是由于LoopingCall在主线程上运行 所以对db的
  • 非阻塞方法中的饥饿

    一段时间以来 我一直在阅读有关非阻塞方法的内容 这是一段所谓的无锁计数器的代码 public class CasCounter private SimulatedCAS value public int getValue return va
  • MoveWindow死锁?

    我在线程 A 上有一个窗口 它在某个时刻 由于在其 wndproc 上收到消息 触发线程 B 上的操作 然后等待该操作完成 使用某种同步机制 然后线程B调用MoveWindow 在线程 A 的窗口 例如标准文本框 内移动子窗口 此时程序由于
  • 如何在c#中指定时间后取消后台工作者

    如何在 C 中的指定时间后取消后台工作程序或取消无响应的后台工作程序 看看这个教程 http www albahari com threading part3 aspx http www albahari com threading par
  • 线程安全的异步字节队列

    我有一个回调方法 只要有新数据可用 就会调用该方法 public delegate void DataCallback byte buffer int offset int count 我想将其包装在一个实现与此类似的接口的类中 publi
  • 带等待/通知的同步块与不带等待/通知的同步块之间的区别?

    如果我只是使用synchronized 不是wait notify方法 它仍然是线程安全的吗 有什么不同 Using synchronized使方法 块一次只能由一个线程访问 所以 是的 它是线程安全的 这两个概念是结合在一起的 而不是相互
  • 如何在给定点停止线程?

    我试图停止一些线程 阅读一些有关优雅地执行此操作的正确方法的内容 但我一定做错了什么 因为它根本不起作用 起初我尝试不使用lock with IsRunning不稳定 然后尝试使用锁 这是我所拥有的 private volatile boo
  • iPhone 应用程序中的异步、同步、线程

    我正处于一个应用程序的设计阶段 该应用程序将利用 REST Web 服务 并且在使用异步 同步和线程方面遇到了困境 这是场景 假设您有三个选项可供深入研究 每个选项都有自己的基于 REST 的资源 我可以使用同步请求延迟加载每个请求 但这会
  • Interlocked.CompareExchange 的返回值是否有一些充分的理由

    The Interlocked CompareExchange 方法 docs https learn microsoft com en us dotnet api system threading interlocked comparee
  • 使用 Thread.Sleep 等待的替代方法

    首先我不是在问同样的问题C Thread Sleep 的替代方案 https stackoverflow com questions 5450353 c sharp alternative to thread sleep or C 中 Th
  • 无锁算法真的比全锁算法性能更好吗?

    陈雷蒙德 http blogs msdn com b oldnewthing 一直在做一个huge http blogs msdn com b oldnewthing archive 2011 04 15 10154245 aspx ser
  • F#:仅对第一个事件执行一次操作,没有可变性/锁定?

    我有这段代码 可以下载文件并在控制台中告诉我该文件有多大 use webClient new WebClient let lockObj new Object let mutable firstProgressEvent true let

随机推荐