【问题标题】:Concurrent programming Java Threads并发编程 Java 线程
【发布时间】:2017-12-11 00:23:56
【问题描述】:

我被分配了一项上课任务,但是我们只被教到了一定程度,这留下了知识空白。我们被要求完成一些我们在课堂上完成的剩余代码,导师描述了需要做什么而不是如何做,自从我上次做任何独立 Java 工作以来的时间已经大约 7 个月了,所以我下面有点生疏的是我们在导师指导下编写的代码,以及任务描述的下方。

public class CardHolder implements Runnable {
private int id;
private Account account;
final static int numIterations = 20;

public CardHolder(int id, Account account) {
    this.id = id;
    this.account = account;
}

/*
 * run method is what is executed when you start a Thread that
 * is initialised with an instance of this class.
 * You will need to add code to keep track of local balance (cash
 * in hand) and report this when the thread completes.
 */
public void run() {
    for (int i = 0; i < numIterations; i++) {
        // Generate a random amount from 1-10
        int amount = (int)(Math.random()*10)+1;
        // Then with 50/50 chance, either deposit or withdraw it
        if (Math.random() > 0.5) {
            account.withdraw(id, amount); 
        } else {
            account.deposit(id, amount); 
        }
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } 
    }
    System.out.println("THREAD "+ id + " finished"); 

}
}

import java.util.ArrayList;

public class Account {
private String name;

/**
 * @param args
 */
public static void main(String[] args) {
    // Check to make sure program has been called with correct number of
    // command line arguments
    if (args.length != 3) {
        System.err.println("Error: program should take exactly three command line arguments:");
        System.err.println("\t<No. of accounts> <main acct starting bal.> <backup acct. starting bal.>");
        System.exit(0);
    }
    // And then make sure that those args are all integers
    try {
        int numCards = Integer.parseInt(args[0]);
        Account account = new Account("Main", Integer.parseInt(args[1]));
        Account backup = new Account("Backup", Integer.parseInt(args[2]));

        // Your code to create and manage the threads should go here.
    } catch (NumberFormatException e) {
        System.err.println("All three arguments should be integers");
        System.err.println("\t<No. of accounts> <main acct starting bal.> <backup acct. starting bal.>");
    }
}

// Create an account - initalisation goes in here
public Account(String name, int startingBalance) {
}

// Deposit <amount> into the account
public void deposit(int id, int amount) { 
} 

// Withdraw <amount> from the account
public void withdraw(int id, int amount) {
}  

// Print out the statement of transactions
public void printStatement() {
    System.out.println("Account \"" + name + "\":");
}
}

eclipse中运行配置中包含的参数是50 1000 1000

任务

许多银行系统允许多个持卡人访问一个帐户(例如企业
帐户)。这样做的结果是,有可能不止一个人尝试 同时从一个账户取款或存款。如果访问 account 的实现很天真(忽略了并发编程的原则),这个
可能导致竞争条件,以及以下欺诈成功的可能性: 多个持卡人可能串通并试图进行定时攻击。在这样的
一次攻击,多个持卡人同时从账户中取款, 目的是只从账户余额中扣除一项。 你的任务是编写一个程序(详细说明如下)来模拟 使用多张关联卡操作启用 ATM 的关联银行账户。换句话说,
将有几个人可以访问每个帐户,每个人都有自己的卡()。 你的程序应该演示并发编程的原理,使它
上述诈骗不可能成功

任何帮助将不胜感激

谢谢

【问题讨论】:

标签: java concurrency java-threads


【解决方案1】:

好的,您需要担心的主要是存款和取款方式。例如:

public class Account {
    public void deposit(int id, int amount) {
        balance += amount;
    }

    public void withdraw(int id, int amount) {
        balance -= amount;
    }

    private int balance;
}

这样做的问题是递增/递减操作可能不是原子的。在幕后可能会发生几项操作,而不仅仅是一项。例如:

int temp1 = balance;
int temp2 = amount;
int temp3 = temp1 - temp2;
balance = temp3;

如果您有很多线程同时执行此操作,可能会导致您不想要的结果。试着想想为什么。您可以通过使用 synchronized 关键字 来避免这种情况,它会强制整个方法以原子方式执行。我认为它所做的是将类的实例变成 mutex

public class Account {
    public synchronized void deposit(int id, int amount) {
        balance += amount;
    }

    public synchronized void withdraw(int id, int amount) {
        balance -= amount;
    }

    private int balance;
}

为了对此进行测试,我不会使用 Random,因为它不是确定性。我要做的是启动说,1000 个线程同时执行特定数量的提款。如果你有 1,000,000 美元的余额,并且你启动 1000 个线程以提取 1 美元的次数超过 1000 次,那么测试后你的帐户中应该有 0 美元。在添加同步关键字之前尝试模拟错误的答案,并通过添加同步关键字验证它是否已修复。

【讨论】:

    猜你喜欢
    • 2014-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 2011-04-02
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多