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