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

时间:2019-06-02 07:24:45

标签: java multithreading thread-safety race-condition

我是多线程技术的新手,我有一个基本问题,我无法获得答案。假设我有一个名为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类实例,并且会发生数据不一致。

2 个答案:

答案 0 :(得分:1)

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

  2. 如果每个用户都有自己的BankTransaction类实例,则不会慢,因为方法上的锁定是针对对象的(在此实现中,锁定对象为“ this”)。因此,用户(或他们的线程)仅在有另一个用户想要使用完全相同对象的相同方法时才等待(如果每个用户都有自己的实例,情况就不会如此)。

答案 1 :(得分:1)

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

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