java中同步线程的问题

java中同步线程的问题,java,synchronization,synchronized,Java,Synchronization,Synchronized,我正试图编写一个示例程序,它由一个银行账户对象和10个从属对象组成,每个从属对象从两个不同的银行账户对象移动1单位货币一百万次。我的预期结果是银行账户货币的总和在最后为0,就像我开始的那样。我已经尝试在BankAccount中同步“setBalance”方法,因为我认为这是应该同步的方法,但是这不起作用。当我在getBalance或run上尝试时,即使这些也不起作用,所以我不确定我做错了什么 BankAccount.java public class BankAccount{ priv

我正试图编写一个示例程序,它由一个银行账户对象和10个从属对象组成,每个从属对象从两个不同的银行账户对象移动1单位货币一百万次。我的预期结果是银行账户货币的总和在最后为0,就像我开始的那样。我已经尝试在BankAccount中同步“setBalance”方法,因为我认为这是应该同步的方法,但是这不起作用。当我在getBalance或run上尝试时,即使这些也不起作用,所以我不确定我做错了什么

BankAccount.java

public class BankAccount{

    private int balance;

    public BankAccount()
    {
        balance = 0;
    }

    public int getBalance()
    {
        return balance;
    }

    public void setBalance(int balance)
    {
        this.balance = balance;
    }
}
Slave.java

public class Slave extends Thread {

    BankAccount source;
    BankAccount target;

    int currency = 1;

    public Slave (BankAccount source, BankAccount target) {
        this.source = source;
        this.target = target;

    }

    public void run() {
        for (int i = 0; i < 1000000; i++)
        {
            target.setBalance(target.getBalance() + currency);
            source.setBalance(source.getBalance() - currency);
        }
    }
}
公共类从线程扩展{
银行账户来源;
银行账户目标;
国际货币=1;
公共从属(银行帐户源、银行帐户目标){
this.source=源;
this.target=目标;
}
公开募捐{
对于(int i=0;i<1000000;i++)
{
target.setBalance(target.getBalance()+货币);
source.setBalance(source.getBalance()-currency);
}
}
}
Master.java

public class Master {

    public static void main(String[] args) {

        BankAccount account1 = new BankAccount();
        BankAccount account2 = new BankAccount();

        Slave[] slaves = new Slave[10];

        for (int i = 0; i < 10; i++)
        {
            if (i < 5)
            {
                slaves[i] = new Slave(account1, account2);
            }
            else
            {
                slaves[i] = new Slave(account2, account1);
            }
        }

        for (int i = 0; i < 10; i++)
        {
            slaves[i].start();
        }

        try
        {
            for (Slave s : slaves)
                s.join();
        }
        catch (InterruptedException e) {
            System.out.println("Interruption before completion of the joins" + e);
        }


        System.out.println("Sum of balances: " + (account1.getBalance() + account2.getBalance()));
    }
}
公共类主控{
公共静态void main(字符串[]args){
BankAccount ACCOUNT 1=新的BankAccount();
BankAccount account2=新的BankAccount();
从属[]从属=新从属[10];
对于(int i=0;i<10;i++)
{
如果(i<5)
{
从机[i]=新的从机(account1,account2);
}
其他的
{
从机[i]=新从机(account2,account1);
}
}
对于(int i=0;i<10;i++)
{
slaves[i].start();
}
尝试
{
用于(从s:从)
s、 join();
}
捕捉(中断异常e){
System.out.println(“连接完成前的中断”+e);
}
System.out.println(“余额之和:+(account1.getBalance()+account2.getBalance());
}
}

如果在方法签名中使用
synchronized
关键字,则会锁定正在调用的对象。如果希望锁定替代对象,则需要按以下方式使用关键字:

synchronized(objectToLock) {
    doAtomicStuff();
}
在您的情况下,您的原子操作是获取、调整和设置余额,您需要锁定相关的
BankAccount
对象

这应该足以让您确定在何处以及如何使用
synchronized

此代码

。。。仅当T1调用
getBalance()
和调用
setBalance()
之间的
target
平衡未被其他线程修改时,才会在线程T1中产生预期效果。同步这些方法中的一个或两个对阻止这种干预性修改没有任何作用,而且您的多个线程执行这些方法的次数太多,速度太快,您很可能会遇到这个问题

因此,适当的关键区域包含两个方法调用,您可以通过将它们放在
synchronized
块中来实现:

            synchronized(target) {
                target.setBalance(target.getBalance() + currency);
            }

当然,您需要类似地处理
源代码的更新。请注意,对于每个关键区域,所有争用线程都需要在同一个对象上进行同步,以获得所需的效果。

在这个问题中,您缺少的第一件事是如何使用
synchronized
@JoeC true,忘记了包含此内容,在
获取余额
、应用操作(
+
/
-
)和
设置余额
所需的时间之间,实际余额可能已更改。最好有一个同步的
取款
存款
方法。这些方法将操作(
+
/
-
)应用于
余额
本身,在单个受保护的,step@MadProgrammer您是对的,不过这只是一个示例程序,我可以更好地理解“同步”是如何工作的。我想用这段代码来做这件事,不管它有多不实用,我相信它应该在某种方法中与“同步”一起工作。@user3487554,您需要在
运行
方法中同步
目标
银行账户
实例,以确保两者都不能更新。这会变得很危险,因为你可能会进入一个死锁场景,这是我所需要的。非常感谢。
            synchronized(target) {
                target.setBalance(target.getBalance() + currency);
            }