当前位置: 首页 > 知识库问答 >
问题:

Java和同步问题

蒋联
2023-03-14

我在Java写程序,有点担心同步。

这个场景非常“简单”,我们有一个简单的银行账户类,多人可以从账户中取款(虽然他们不能存款),他们也可以检查账户余额。问题是,余额一直在变化,因此我们希望客户查看正确的余额!

到目前为止,这是我的班级。

    class Account implements Serializable {

    private boolean available = false;

    String ac_id;
    String name;
    int balance;

    public Account(String ac_id, String name, int blnc)

    {
        this.ac_id = ac_id;
        this.name = name;
        this.blnc = blnc;

    }

    public synchronized int getMoney(int money) {
        if (money > blnc) {
            return -1;
        }
        while (available == true) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }

        blnc -= money;
        available = true;
        notifyAll();
        return 1;
    }

    public synchronized int chkBalance() {

        return blnc;
    }

    @Override
    public String toString()

    {
        return "Balance: " + chkBalance();
    }

}

正如您可以看到的,通过这个实现,我可以确保有人可以从一个account对象获得资金,但是这个account对象被阻止了,然后一个解决方案出现了

public synchronized int chkBalance()   

添加available=false的方法这似乎解决了我的问题,但我真的不能说这是否正确,我的意思是它们是否确实同步,客户是否看到了正确的平衡。

提前谢谢!!

理论上,如果我只是在这两种方法之前使用同步词,那不是很好吗?我的意思是,一次只有一个线程会占用每个方法,既然不需要存款,那么使用布尔值可用的true/false有什么意义?

共有3个答案

吕亮
2023-03-14

... 多人可以从账户中取款[而且]他们还可以检查余额。。。[但是],余额一直在变化,因此我们希望客户查看正确的余额!

你不能。如果其他人(线程)可以随时取款,那么就没有正确的余额。你所能保证的最好是正确的平衡。也就是说,通过正确的同步,您可以确保checkBalance()返回的数字在过去的某个时刻是正确的。

这就是问题所在。某些函数fubar()调用check Balance()。为什么啊?为什么它关心平衡是什么?一旦check Balance()返回,调用线程就不再同步。任何其他线程都可能在check Balance()返回的时间和fubar()处理信息的时间之间进行撤回。

如果fubar()需要知道平衡以便处理信息,那么fubar()也需要同步。

赫连黎昕
2023-03-14

如果您不关心执行速度,那么您需要做的就是使方法同步。这将保证一个特定帐户对象的每个方法一次只能被一个线程访问。您的可用标志在您的实现中似乎没有用。在同步的方法中放入等待()也是没有意义的;这只会减慢等待对象锁的其他线程。

同步getMoney()尤为重要,因为此方法会更改blnc的值,如果不同步,可能会导致两个线程同时覆盖该值,在这种情况下,一个线程将无法生效。

在您的实现中,如果chkBalance()是同步的,这并不重要,因为它不写入blnc。如果此方法与getMoney()同时调用,它将在对blnc进行更改之前或之后返回blnc的值,并且这种调度超出了程序员的控制范围。

不同步chkBalance()也很有用,因为您可能会从不同的线程同时调用chkBalance(),并且这些调用中没有相互等待的意义。

要确保从共享内存中获取blnc的最新值,而不是本地缓存的值,请考虑使blnc变量易失性。

林元明
2023-03-14

您根本不需要可用的布尔值。只同步getMoney方法并使blnc不稳定就足够了,这样其他检查更改的线程就可以看到它们。尝试类似的东西:

class Account implements Serializable {

final String ac_id;
final String name;
volatile int blnc;

public Account(String ac_id, String name, int blnc) {
    this.ac_id = ac_id;
    this.name = name;
    this.blnc = blnc;
}

public synchronized int getMoney(int money) {
    if (money > blnc) {
        return -1;
    }
    blnc -= money;
    return 1;
}

public int chkBalance() {
    return blnc;
}

@Override
public String toString() {
    return "Balance: " + chkBalance();
}
}
 类似资料:
  • 问题内容: Java文档说“同一对象上的同步方法的两次调用不可能交错”。我需要知道的是,synchronized是否还会阻止 同一类的 两个不同 实例中的 同步方法交织。 例如,类Worker具有称为process()的方法。我们有几个在自己的线程中运行的Worker实例。我们希望防止多个实例同时运行process()方法。会 同步 吗? 谢谢。 问题答案: 没有; 仅防止多个线程在 同一 实例中

  • 我试图更好地理解Java多线程。所以,我知道这句话说只有一个线程可以访问一个对象实例,从而调用该实例的方法(例如,在这种情况下,类 中的减方法。 但是,当你仍然有相同的 会发生什么,但两个线程与不同的 相关联,完全试图调用 的方法?我以为不的消息永远不会被打印出来,但它确实打印出来了。毕竟,仍然只有一个对象实例 ,这是否意味着同步不适用于此示例?

  • 本文向大家介绍Spring注解和同步锁不能同步问题解决,包括了Spring注解和同步锁不能同步问题解决的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了Spring注解和同步锁不能同步问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 结论:如果在service层的方法上同时使用事务和同步锁无法保证数据同步。 上面这个例子无法保证数

  • 问题内容: 我面临pthread的同步问题。threadWaitFunction1,是线程等待函数。我希望行号。仅在243-246完成后才执行247 。但我感到奇怪的是,有时它会在243-246完成之前直接跳到247。 请帮我。 提前致谢。 创建并调用上述线程的线程是: 如果我使用pthread_mutex_lock保护整个函数,但仍然存在相同的问题。 如何确保有序执行?有人可以帮忙吗? 编辑:n

  • 我正在尝试创建一个回调函数: 首先,我创建了一个函数接口,用于定义回调函数的约定 我创建了一个类,该类将定义一个方法来调用我的回调(我通过使用lambda表达式传递了接口的实现作为对此方法的引用) 下面是我的代码: 但当我运行这段代码时,我得到了这样的结果。 有人能告诉我为什么我会有这个例外吗?