使用AtomicInteger时的同步 [英] Synchronization while using AtomicInteger

查看:141
本文介绍了使用AtomicInteger时的同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们假设我想实现一个非常简单的银行帐户类,并且我们要关注并发和多线程问题,

Let's assume that I want to implement a very simple Bank Account class , and we want to take care about concurrency and multi-threading issues,

这是一个好主意,使以下方法 synchronized 即使 balance AtomicInteger 吗?

Is it a good idea to make the following methods synchronized even though balance is AtomicInteger ?

另一方面,如果我们将所有方法都设为synchronized,则不会使用 AtomicInteger , 对 ?

On the other hand , if we have all the methods as synchronized , there would be no use of AtomicInteger anymore , right ?

import java.util.concurrent.atomic.AtomicInteger;


public class Account {
    AtomicInteger balance;
    public synchronized int checkBalance(){
        return this.balance.intValue();
    }
    public synchronized void deposit(int amount){
        balance.getAndAdd(amount);
    }
    public synchronized boolean enoughFund(int a){
        if (balance.intValue() >= a)
            return true;
        return false;
    }
    public synchronized boolean transfer_funds(Account acc, int amount){ // dest : acc 
        if (enoughFund(amount)){
            withdraw(amount);
            acc.deposit(amount);
            return true;
        }
        return false;
    }
    public synchronized boolean withdraw(int amount){
        if (checkBalance() < amount)
            return false;
        balance.getAndAdd(-1 * amount);
        return true;
    }
}


推荐答案

您声明为 AtomicInteger 的金额不会阻止线程在方法执行过程中被抢占(如果它不同步)。例如,如果你的方法 transfer_funds 没有以任何方式同步,你可能会得到意想不到的结果,即使你的金额将 AtomicInteger

Having your amount declared as AtomicInteger does not prevent the thread from being preempted in the middle of method execution (if it's not synchronized). So for example if your method transfer_funds were not synchronized in any way, you could get unexpected results, even though your amount will be AtomicInteger

public /* synchronized */ boolean transfer_funds(Account acc, int amount){ // dest : acc 
        if (enoughFund(amount)){
            withdraw(amount);  // <- thread can be preempted in the middle of method execution
            acc.deposit(amount);
            return true;
        }
        return false;
    }

这样的问题称为竞争条件。一个可能的例子是两个线程尝试从同一个帐户转移资金。当一个线程确定有 enoughFund 执行信用转移时,该线程可能被抢占,同时其他线程可以开始从该帐户转移资金。当第一个线程再次开始处理时,它不会检查是否有 enoughFunds 执行信用转移(他已经检查了它,但他的知识可能已过时),但它转到下一行执行。这样,您可能无法获得一致的结果。

Such problems are called race conditions. One possible example is when two threads try to transfer funds from the same account. When one thread determines that there is enoughFund to perform credit transfer, that thread may be preempted and at the same time other thread can start transfering funds from this account. When the first thread starts processing again it does not double-check if there is enoughFunds to perform credit transfer (he already checked it, but his knowledge may be outdated), but it goes to the next line of execution. This way you may not get consistent results. The total amount that you had at the beginning on all accounts can be changed.

在Cay Horstmann的核心Java书中有一个很好的解释,这里是< a href =http://horstmann.com/corejava/cj7v2ch1.pdf =nofollow>关于同步的章节可免费使用。它详细描述了几乎完全相同的问题,你问。

There is a very good explanation of this aspect in Cay Horstmann's Core Java book - here is chapter about synchronization available for free. It describes in detail almost exactly the same problem you are asking about.

这篇关于使用AtomicInteger时的同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆