Thread - Race Condition

In most practical multithreaded applications, two or more threads need to share access to the same data, What

happens if two threads have access to the same object and each calls a method that modifies the state of the

object? As you might imagine, the threads can step on each other's toes. Depending on the order in which the 

data were accessed, corrupted objects can result. Such a situation is often called a "Race Condition".

I recommend that readers first consider the following program. It is best to practice this simple program; and in the next paragraph, I will explain the "Race Condition".

The simple program simulates funds transfering from one account to another in a bank. We simulated an array of accounts transfering funds to each other randomly.

package ConcurrentTest;

import java.util.Arrays;

/**
 * Created by lenovo on 2018/6/13.
 */
public class Bank {
    private final double[] accounts;

    public Bank(int n, double initialBalance) {
        accounts = new double[n];
        Arrays.fill(accounts, initialBalance);
    }

    public void transfer(int from, int to, double amount) {

        if (accounts[from] < amount) {
            return;
        }

        System.out.print(Thread.currentThread());
        accounts[from] -= amount;
        System.out.printf(" %10.2f from %d to %d", amount, from, to);
        accounts[to] += amount;
        System.out.printf(" Total Balance: %10.2f\n", getTotalBalance());

    }

    private double getTotalBalance() {
        double sum = 0;

        for(double account : accounts) {
            sum += account;
        }

        return sum;
    }

    public int size() {
        return accounts.length;
    }

}
package ConcurrentTest;

/**
 * Created by lenovo on 2018/6/13.
 */
public class UnsynchBankTest {
    public static final int NACCOUNTS = 100;
    public static final double INITIAL_BALANCE = 1000;
    public static final double MAX_AMOUNT = 1000;
    public static final int DELAY = 10;

    public static void main(String[] args) {
        Bank bank = new Bank(NACCOUNTS, INITIAL_BALANCE);

        for (int i = 0; i < bank.size(); i++) {
            int fromAccount = i;

            Runnable r = () -> {
                try {
                    while (true) {
                        int toAccount = (int) (bank.size() * Math.random());
                        double amount = MAX_AMOUNT * Math.random();
                        bank.transfer(fromAccount, toAccount, amount);
                        Thread.sleep((int) (DELAY * Math.random()));
                    }
                } catch (Throwable e) {
                    Thread.currentThread().interrupt();
                }
            };

            new Thread(r).start();
        }

    }

}

About the previous program, the "Race Condition" occurs when two threads are simultaneously trying to update an account. Support two threads simultaneously carry out the instruction:

accounts[to] += amount;

The problem is that these are not atomic operations. The instruction might be processed as follows:

1. Load "account[to]" into a register.

2. Add "amount".

3. Move the result back to "account[to]".

Now, suppose the first thread executes Steps 1 and 2, and then it is preempted.

Suppose the second thread awakens and updates the same entry in the "account" array. Then, the first thread awakens and completes its Step 3.That action wipes out the modification of the other thread. As a result, the total is no longer correct.

NOTE: You can actually peek at the virtual machine bytecodes that execute each statement in our class. Run the command:

javap -c -v Bank

to decompile the "Bank.class" file. For example, the line

accounts[to] += amount;

is translated into the following bytecodes:

aload_0
getfield    #2;  //Field accounts:[D
iload_2
dup2
daload
dload_3
dadd
dastore
What these codes mean does not matter. The point is that the increment command is made up of several instructions, and the thread executing them can be interrupted at any instruction.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值