我只找到了同步一個 String 物件的答案,而不是兩個。
這不是一項真正的任務,而是一項任務。我有 SomeLibrary 可以將錢從一個帳戶轉移到另一個帳戶。我無法訪問 Account 物件來鎖定它。我只能使用 SomeLibrary.transfer(String from, String to),它不是執行緒安全的。我有將帳戶 ID 作為字串的方法。我需要在沒有死鎖的情況下鎖定這兩個字串。
到目前為止我所做的是:
使用 .intern 方法創建新字串(String fr = from.intern())。但這是不好的做法,我不允許使用這種方法。但它奏效了。
從舊的 (String fr = new String(from)) 創建新字串。這也有效(我沒有死鎖)但我懷疑這個解決方案。
還有其他方法可以鎖定兩個字串嗎?
我嘗試使用 ConcurrentHashMap 并將字串放在那里,但沒有用。
可能有一種方法可以將字串放入某些物件中,但是應該在哪里創建這些物件?我可以在 transfer() 中創建它們,但是在區域變數上同步也不是一個好習慣。
我的方法是:
public void transfer(String from, String to, int amount) {
String fr = new String(from);
String too = new String(to);
int fromHash = System.identityHashCode(fr);
int toHash = System.identityHashCode(too);
if (fromHash < toHash) {
synchronizedTransfer(from, to, amount, fr, too);
} else if (fromHash > toHash) {
synchronizedTransfer(to, from, amount, too, fr);
} else {
synchronized (tieLock) {
synchronizedTransfer(from, to, amount, fr, too);
}
}
}
private void synchronizedTransfer(String from, String to, int amount, String fr, String too) {
synchronized (fr) {
synchronized (too) {
SomeLibrary.transfer(from, to);
}
}
}
uj5u.com熱心網友回復:
您可以使用嵌套的同步塊和存盤專用同步物件的資料結構在兩個物件上進行同步。為了防止出現任何死鎖,我會按字典順序比較兩個字串:
private static final Hashtable<String, Object> syncTable = new Hashtable<>();
private static final Object syncOnEquals = new Object();
public void transfer(String from, String to, int amount) {
Object syncFrom = syncTable.computeIfAbsent(from, s -> new Object());
Object syncTo = syncTable.computeIfAbsent(to, s -> new Object());
int comparingResult = from.compareTo(to);
if (comparingResult > 0) {
synchronized (syncFrom) {
synchronized (syncTo) {
SomeLibrary.transfer(from, to);
}
}
} else if (comparingResult < 0) {
synchronized (syncTo) {
synchronized (syncFrom) {
SomeLibrary.transfer(from, to);
}
}
} else {
synchronized (syncOnEquals) {
SomeLibrary.transfer(from, to);
}
}
}
如果您不熟悉 lambda 運算式:
Object syncFrom = syncTable.computeIfAbsent(from, s -> new Object());
相當于
Object syncFrom;
synchronized (syncTable) {
syncFrom = syncTable.get(from);
if (syncFrom == null) {
syncFrom = new Object();
syncTable.put(from, syncFrom);
}
}
uj5u.com熱心網友回復:
必須明確的是,對于傳輸(from, to) 所有 (from, ), ( , from), (*, to), (to, *)傳輸可能需要受到保護。
做到這一點的唯一方法是同步 from 和同步 to。當有傳輸(到,從)時,這可能會導致死鎖。為此,可以訂購 from 和 to,以便同步 AAA 出現在同步 BBB 之前。
另一種方法是將原子存款(from, -amount)、存款(to, amount) 和所有都放在可以回滾的事務中。
現在在同步物件上:這必須是唯一的 Object 實體。您可以使用帳戶 ID 字串,就像放在Map( Set) 中一樣。因此,您有一個唯一的物件作為地圖中的鍵。當然,地圖操作也會受到并發性的影響,請使用:Collections.synchronizedMap。您需要更新它,添加/洗掉帳戶 ID。
由于事務是一個單獨的主題,因此按規范順序嵌套兩個同步。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/381640.html
上一篇:從資料框中的字串中提取浮點值
下一篇:從包含多個模式的串列中查找字串
