处理现实世界中银行交易的并发请求

问题描述 投票:0回答:3

经典的银行余额问题,我试图在一个帐户上执行多次存款/取款交易。

我已经同步了account类中的两个方法,只有加入所有线程(等待执行完成),执行结束时账户余额才为500

所以我正在考虑一个现实世界的场景,其中每个请求都会生成一个新线程来执行事务并返回余额。每次报告的余额是否不正确,因为有其他线程在同一帐户上运行?

这是代码:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;


 class Account {

    private int balance = 0;


    Account(int bal){
        this.balance =bal;
    }

    public int getBal() {
        return balance;
    }


    public synchronized void withdraw(int bal){
       balance = balance - bal;
   }

     public  synchronized void deposit(int bal){
            balance = balance + bal;
        }
     }

public class TransactionManagerNaiveSync implements Runnable {

    Account account;

    public TransactionManagerNaiveSync(Account a){
     this.account = a;
    }
    public static void main(String[] args) {

        long start = System.currentTimeMillis();
         Account a1 = new Account(500);
        TransactionManagerNaiveSync t1 = new TransactionManagerNaiveSync(a1);

        List<Thread> thread = new ArrayList<Thread>();
        for(int i=0;i < 300;i++) thread.add(new Thread(t1));
        for(int i=0;i < 300;i++) thread.get(i).start();
        for(int i=0;i < 300;i++){
            try {
                thread.get(i).join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        long end = System.currentTimeMillis();
        System.out.println(" Account Balance in the end : "+ a1.getBal());
        System.out.println(" Time Taken : "+(end - start));
    }



    @Override
    public void run() {

        //for(int i=0;i < 100;i++)
        //{
            account.deposit(10);
            System.out.println(""+Thread.currentThread().getId()+" Account Balance after deposit : "+account.getBal());
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            account.withdraw(10);
            System.out.println(""+Thread.currentThread().getId()+" Account Balance after withdrawal : "+account.getBal());
        //}

    }

}
java multithreading concurrency
3个回答
4
投票

平衡可能不正确,因为您没有同步

Account.getBal()
,这意味着您可能无法获得最新值,因为内存可见性保证不可用于对多个线程更新的变量的非同步访问。

简单标记方法

synchronized

如果您将余额存储为

AtomicInteger
而不是
int
,也会更容易(并且几乎肯定更高效),因为那时您根本不需要
synchronize


2
投票

我已经同步了这两种方法...

所以我正在考虑一个现实世界的场景...每次报告的余额是否不正确,因为同一帐户上有其他线程在运行?

嗯,这取决于你所说的“正确的平衡”是什么意思。如果其他线程可以在您请求它的时间和您打印它的时间之间更改它,那么正确的平衡是什么? 在多线程环境中,关于“正确”含义的不同想法被称为

一致性模型

一种非常容易理解的一致性模型称为“静态一致性”。如果您的程序是静态一致的,则意味着当所有线程同时空闲时,平衡在任何时刻都是正确的(这里,“空闲”是指执行任何不影响平衡的操作)。它很容易定义,但测试起来可能很棘手:如果这样的时刻从未发生过怎么办?

另一个一致性模型称为线性化。线性化的一个简单定义是,如果余额每次都“正确”,并且在“精确的瞬间”,当您的一个线程释放用于保护余额的锁时,您的程序就是可线性化的。

使用 @GuardedBy(“这个”)


0
投票

© www.soinside.com 2019 - 2024. All rights reserved.