首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >使用AtomicInteger时的同步

使用AtomicInteger时的同步
EN

Stack Overflow用户
提问于 2013-06-22 17:10:49
回答 5查看 7K关注 0票数 10

假设我想实现一个非常简单的Bank Account类,并且我们想要处理并发和多线程问题,

尽管balanceAtomicInteger,但将以下方法设置为synchronized是个好主意吗?

另一方面,如果我们所有的方法都是同步的,那么就不会再使用AtomicInteger了,对吧?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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;
    }
}
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-06-22 17:16:08

将数量声明为AtomicInteger并不能防止线程在方法执行过程中被抢占(如果它不是同步的)。因此,例如,如果您的方法transfer_funds没有以任何方式进行同步,那么即使您的数量将是AtomicInteger,您也可能得到意想不到的结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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来执行信用转移(他已经检查过了,但他的知识可能已经过时了),但它会进入下一行执行。这样你可能得不到一致的结果。您在所有帐户上开始时的总金额都可以更改。

在Cay Horstmann的Core Java一书中对这方面有一个非常好的解释--这是免费提供的chapter about synchronization。它详细地描述了您正在询问的几乎完全相同的问题。

票数 8
EN

Stack Overflow用户

发布于 2013-06-22 17:17:34

是的,对于两者都是,这是一个好主意,使它同步,原子是不需要的。

如果您简单地依赖于原子而不是同步,那么您可能会遇到如下问题:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    if (enoughFund(amount)){
        withdraw(amount);
        acc.deposit(amount);
        return true;
    }

因为原子只保证您的整数不会被同时访问,这意味着即使amount是由其他线程写入的,也可以保证enoughFund(amount)提供正确的值。然而,原子本身并不能保证此行获得的值与下一行代码中的值相同,因为另一个线程可以在这两行之间执行另一个原子操作,从而导致withdraw(amount);能够将余额设置为零。

票数 7
EN

Stack Overflow用户

发布于 2013-06-22 19:02:33

如果你非常想使用AtomicInteger,你可以这样写:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Account {
    private final AtomicInteger balance = new AtomicInteger(0);

    public void deposit(int amount) {
        balance.getAndAdd(amount);
    }

    public boolean withdraw(int amount) {
        for (int i; i < SOME_NUMBER_OF_ATTEMPTS; ++i) {
            int currentBalance = balance.get();
            if (currentBalance < amount) return false;
            boolean updated = balance.compareAndSet(currentBalance, currentBalance - amount);
            if (updated) return true;
        }
    }

    public boolean transfer(int amount, Account recipient) {
        boolean withdrawn = withdraw(amount);
        if (withdrawn) recipient.deposit(amount);
        return withdrawn;
    }
}

这是安全的,而且它不使用锁。进行传输或提取的线程不能保证永远都会完成这一操作,但是嘿。

循环执行比较和设置的技术是一种标准技术。这就是synchronized使用的锁本身是如何实现的。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17253260

复制
相关文章
关于AtomicInteger里面addAndGet如何保证同步的(compareAndSwapInt原理)
比如我们使用new AtomicInteger(1);就会加载类,static静态代码块执行。使用的反射的机制得到名字是value的Field对象,再根据objectFieldOffset这个方法求出value这个变量在该对象内存中的偏移量valueOffset 。
砖业洋__
2023/05/06
1180
AtomicInteger、AtomicBoolean、AtomicLong等原子类的使用
我们看两个线程输出的count值都是0这显然是不正确的,原因就是因为++这个操作符不是一个原子操作。我们可以把这个操作符拆分开来看一下它的实现逻辑。
吉林乌拉
2019/08/14
9180
(十七)AtomicInteger原子类的介绍和使用
(十二)yield、notify、notifyAll、sleep、join、wait的区别
HaC
2021/05/20
8700
CAS && AtomicInteger
AtomicInteger package java.util.concurrent.atomic; import java.util.function.IntUnaryOperator; import java.util.function.IntBinaryOperator; import sun.misc.Unsafe; public class AtomicInteger extends Number implements java.io.Serializable { private
大学里的混子
2019/03/31
7260
AtomicInteger详解
因为在阻塞队列中LinkedBlockingQueue中对容量的维护使用了Atomic类,所以需要对该类学习下,如何使用AtomicInteger来保证线程操作的原子性。
虞大大
2020/08/26
1K0
AtomicInteger 源码分析
AtomicInteger 扩展了 Number,适用于基于数字的处理,并提供了如原子递增等,适合一些计数场景
itliusir
2020/01/31
4990
源码阅读 AtomicInteger
AtomicInteger 原子整数 可以原子更新的int值。 用于原子递增计数器等应用程序中,不能用作java.lang.Integer的替换。 扩展了Number。 # 1.继承关系: public class AtomicInteger extends Number implements java.io.Serializable # 2. 属性、代码块: // Unsafe的实例 private static final Unsafe uns
微风-- 轻许--
2022/04/13
2200
AtomicInteger源码解析
Java并发编程里不得不提java提供的高并发工具包,JUC包提供丰富的并发编程工具类,因此学习Java并发编程,JUC包就是学习的基础。在学习JUC包之前,我们先了解一下JUC的基本功能模块.
写一点笔记
2020/08/25
2960
java voliate_Java之voliate, synchronized, AtomicInteger使用
用在多线程,同步变量。 线程为了提高效率,将成员变量(如A)某拷贝了一份(如B),线程中对A的访问其实访问的是B。只在某些动作时才进行A和B的同步。因此存在A和B不一致的情况。volatile就是用来避免这种情况的。volatile告诉jvm,它所修饰的变量不保留拷贝,直接访问主内存中的(也就是上面说的A) ,但是不能用其来进行多线程同步控制
全栈程序员站长
2022/08/13
4150
多线程 里面 使用AtomicInteger类,保证线程安全
假设我们的网站要统计用户人数,我们需要通过变量的自增来实现:count++; 这个操作存在线程安全问题:
一写代码就开心
2022/08/03
9000
大文件同步时 同步慢、同步中断怎么办?
现代企业中,企业结构分散化不断扩大,比如多个研发中心、多个分支机构等等,企业需要把内部各种业务数据在多台服务器之间、多个数据中心之间,乃至多云和本地之间调度和同步。如何保证多个设备之间的数据一致性以及如何高效地进行文件同步成为了人们关注的焦点。
企业文件数据交换
2019/11/12
1.6K0
大文件同步时 同步慢、同步中断怎么办?
AtomicInteger 核心源码解析
原子类使用 CAS 替代锁,实现基本类似,我们本文以 AtomicInteger 为例来研究其究竟是如何实现无锁同步的.
JavaEdge
2020/05/06
3590
AtomicInteger 核心源码解析
AtomicInteger 核心源码解析
原子类使用 CAS 替代锁,实现基本类似,我们本文以 AtomicInteger 为例来研究其究竟是如何实现无锁同步的.
JavaEdge
2020/05/26
4560
JAVA 中无锁的线程安全整数 AtomicInteger介绍和使用
转载自 http://blog.csdn.net/bigtree_3721/article/details/51296064
allsmallpig
2021/02/25
1.3K0
AtomicInteger源码分析详解
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
suveng
2019/09/18
6740
AtomicInteger源码分析详解
一直使用AtomicInteger?试一试FiledUpdater
在进入正题之前,这里先提出一个问题,如何在多线程中去对一个数字进行+1操作?这个问题非常简单,哪怕是Java的初学者都能回答上来,使用AtomicXXX,比如有一个int类型的自加,那么你可以使用AtomicInteger 代替int类型进行自加。
用户5397975
2019/10/13
6080
17.AtomicInteger、AtomicBoolean的底层原理
老王:是啊,之前我们只是简单介绍了Atomic的体系,今天我们就要进入Atomic底层原理的的学习了,首先我们从AtomicInteger这个比较简单的原子类开始,在说AtomicInteger的底层原理之前呢,我先给你看两个例子:
终有救赎
2023/10/16
2440
17.AtomicInteger、AtomicBoolean的底层原理
centos使用rsync同步文件时遇到的莫名错误解决方法
在centos服务端配置好rsync以后, 在另外一台centos机器上执行同步命令,出现错误提示: rsync: server sent "rsync: link_stat "/–daemon" failed: No such file or directory (2)" rather than greeting rsync error: error starting client-server protocol (code 5) at main.c(1503) [receiver=3.0.6] 基
用户2135432
2018/06/04
2.4K0
点击加载更多

相似问题

AtomicInteger处理同步吗?

14

AtomicInteger与同步的getters/setters

20

AtomicInteger比同步慢

17

AtomicInteger是同步原语吗?

30

AtomicInteger与同步数据块

116
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文