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

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


案例 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 个用户正在使用 BankTransaction 类的同一个实例(因为它是基于应用程序的单例)并使用方法 doSomeTransaction(),这 1000 个用户中的每个用户的请求会很慢吗?因为它是同步的并且可以线程安全地工作。所以,这是不好的方法。我的理解正确吗?

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


至尊宝的传说
浏览 88回答 2
2回答

撒科打诨

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

HUX布斯

在第一种情况下,1000 个用户(或他们的线程)将等待很长时间,因为一次只有一个人可以访问该方法。所有其他人都必须等待锁定才能访问此方法。所以,是的,它会很慢。如果每个用户都有自己的 BankTransaction 类实例,它不会很慢,因为方法上的锁是针对一个对象的(锁对象在这个实现中是“this”)。因此,用户(或他们的线程)只有在有另一个用户想要对完全相同的对象使用相同的方法时才会等待(如果每个用户都有自己的实例,情况就不应该如此)。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java