如何确保两个线程访问相同的资源并使它们线程安全?

How to make sure two thread access same resource and make them Thread safe?

我是多线程的新手,我有一些基本问题无法得到解答。假设我有一个名为 BankTransaction 的 class,我想在其中处理多线程情况。

案例 1(基于应用程序的单例)

@Singleton (Application based singleton)
class BankTransaction {
    synchronized void doSomeTransaction() {
        // write operation
    }
}

案例 2(基于请求的单例)

@Singleton (Request based singleton)
class BankTransaction{
    synchronized void doSomeTransaction() {
        // write operation
    }
}

问题

请耐心等待并通俗易懂地解释一下,因为我需要把事情弄清楚。

  1. 在案例 1 中,如果 1000 个用户正在使用 class BankTransaction 的同一个实例(因为它是基于应用程序的单例)并使用方法 doSomeTransaction(),请求每个1000个用户都会变慢?因为它是同步的并且可以线程安全地工作。所以,这是不好的方法。我的理解正确吗?

  2. 在情况 2 中,如果相同的 1000 个用户正在使用 class BankTransaction 的 doSomeTransaction() 方法,每个用户将获得自己的 class BankTransaction 实例并且它他们中的任何一个都不会慢。但是,例如,在这 1000 个用户中,其中 2 个是密切相关的(丈夫和妻子)并且正在访问同一个银行帐户并同时执行 doSomeOperation() 方法时,我该如何处理竞争条件。我该如何处理?因为它们又都有 2 个不同的 class BankTransaction 实例,因此会发生数据不一致。

  1. 在第一种情况下,1000 个用户(或他们的线程)将等待很长时间,因为一次只有一个人可以访问该方法。所有其他人都必须等待锁定才能访问此方法。所以,是的,它会很慢。

  2. 如果每个用户都有自己的 class BankTransaction 实例,它不会很慢,因为方法上的锁是针对对象的(锁对象将是 "this" 在这个实现中)。因此,用户(或他们的线程)只有在有另一个用户想要对完全相同的对象使用相同的方法时才会等待(如果每个用户都有自己的实例,情况就不应该如此)。

  1. 是的。你的理解是正确的。如果您不想以某种方式允许多个用户更改对象的状态,则应该使方法同步。该示例可以是应用程序级配置对象。

  2. 现在,有很多解决方案。最简单的方法是将此问题推迟到某些 ORM 解决方案,该解决方案可以进一步使用记录级锁定技术或其他任何技术。但是,如果您想手动处理这个问题,最简单的方法是在 db 中维护一个列。现在,每次修改记录时,都应该增加该值。在提交记录之前,您应该检查该值是否与您从数据库中获取的记录的值相同。如果相同,那么您可以确定自您开始交易以来没有人修改过它。但是,如果值不相同,您可以向用户抛出一个错误,说记录已被其他用户修改。