我需要在账户之间实现一些基本的资金转移逻辑。为了保持转账的一致性,我利用了同步锁。
这是帐户对象:
class Account {
UUID id;
double balance;
}
这是在transfer worker类中:
public void transfer(Account source, Account target) throws InterruptedException {
Object firstLock = target.id.compareTo(source.id) > 0 ? target : source;
Object secondLock = target.id.compareTo(source.id) < 0 ? target : source;
synchronized (firstLock) {
synchronized (secondLock) {
// Money tranfer logic
}
}
}
我的问题是,如果source Account没有足够的资金,我计划等待该线程,直到它从其他运营中获得资金。对于这个,我一直在等待源帐户。但它以死锁告终,因为目标帐户锁仍在我的帐户上。我怎样才能做到这一点?你能告诉我解决这个问题的正确方法吗?
这就是我试图推迟资金转移的来源账户
public void transfer(Account source, Account target) throws InterruptedException {
Object firstLock = target.id.compareTo(source.id) > 0 ? target : source;
Object secondLock = target.id.compareTo(source.id) < 0 ? target : source;
synchronized (firstLock) {
synchronized (secondLock) {
while(source.balance <= 0 ) {
source.wait();
}
// Money tranfer logic
source.notifyAll();
}
}
}
谢谢。
每当您运行任何等待代码
时,您都需要处理InterruptedExctive
。此外,在调试时添加特定的等待时间也是一个很好的做法,这样您就可以在特定的等待时间后重新加载您的当时循环。
以下是一个修改代码的示例,它可能会帮助您
synchronized (firstLock) {
synchronized (secondLock) {
while(s.balance <= 0 ) {
//surround with InterruptedException otherwise code won't execute
try {
s.wait(1000); // it is good to wait for specific milliseconds, in this case it's 1000 millis.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// Money transfer logic
s.notifyAll();
}
}
对不起,但是你已经改变了你的问题,所以我也在更新我的答案
这里新添加的代码,你不能使用静态源代码,目标。当循环运行时,你需要从数据库更新。
public class Z {
public static void main(String a[]){
Account s = new Account("1");
Account t = new Account("4");
try {
transfer(s, t);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void transfer(Account source, Account target) throws InterruptedException {
Account firstLock = target.id.compareTo(source.id) > 0 ? target : source;
Account secondLock = target.id.compareTo(source.id) < 0 ? target : source;
double sourceBalance = 0;
double targetBalance = 0;
synchronized (firstLock) {
synchronized (secondLock) {
while(sourceBalance <= 4 ) {
source.wait(1000);
System.out.println("waiting... ");
sourceBalance = sourceBalance+1; //get source balance from somewhere else realtime. for me im just updating
}
// Money tranfer logic
targetBalance = 0; //get target balance from server or where you stored;
targetBalance +=sourceBalance;
//send target balance where you want
System.out.println("Money transferred");
source.notifyAll();
}
}
}
}
class Account {
String id;
public Account(String id){
this.id = id;
}
}
我只在一个字符串对象上找到了同步的答案,而不是两个。 这不是一项真正的任务,而是一项任务。我有一个图书馆可以把钱从一个账户转到另一个账户。我无法访问帐户对象以锁定它。我只能用图书馆里的东西。传输(字符串从、字符串到),这不是线程安全的。我有一个帐户ID为字符串的方法。我需要在没有死锁的情况下锁定这两个字符串。 到目前为止,我所做的是: > 使用创建了新字符串。intern方法(字符串fr=from
问题内容: 我想知道如果在同一个对象上同步两次,在Java中是否会出现任何奇怪的行为? 场景如下 两种方法都使用该对象并对其进行同步。当第一个方法调用第二个方法时,它会被锁定而停止吗? 我不这么认为,因为它是同一个线程,但是我不确定是否可能会出现其他任何奇怪的结果。 问题答案: 同步块使用 可重入 锁,这意味着如果线程已经持有该锁,则它可以重新获取它而不会出现问题。因此,您的代码将按预期工作。 请
我遇到了一些使用c#的/关键字进行异步编程的最佳实践(我是c# 5.0的新手)。 给出的建议之一如下: 稳定性:了解您的同步上下文 ...一些同步上下文是不可重入的和单线程的。这意味着在给定时间只能在上下文中执行一个工作单元。这方面的一个例子是Windows UI线程或ASP.NET请求上下文。在这些单线程同步上下文中,很容易死锁。如果您从单线程上下文中生成一个任务,然后在上下文中等待该任务,您的
但是,这并不适用于String类。请参见下面的代码: 这是因为字符串类和自声明类之间的差异吗?谢谢你的帮助!
我试图理解java中同步块的概念。根据我读过的文档,我明白如果我们获取一个锁(使用实例变量的同步块),那么我们就不能在该类中的同一对象上获取同步锁。但是当我尝试实际使用以下片段时,我发现我的理解出了问题。 即我能够同时以两种不同的方法获取锁(同一实例变量上的同步块)。当线程启动时,它将转到run方法并无限期地等待,并且不会从同步块中出来。同时,如果我使用相同的线程调用stop方法,它会进入同步块并
我正在寻找有关同步块的澄清。考虑一下这个类 - A是单例。getValue在整个应用程序中被多个线程大量访问。我添加了一个新方法remove,它从映射中删除一个键。如果如上所述执行删除, 当线程位于remove方法的同步块中时,我假设它将获取map对象上的锁。这是否意味着其他试图通过getValue方法访问映射的线程将被阻止?(我希望他们这样做。) 当remove方法的同步块中没有线程时,访问ge