[英]java threads alternative to synchronization
我是並發編程的新手,我在使用 Java 線程的以下代碼中遇到了一些問題。
狀態類(此類跟蹤位置可用性):
public class Status {
private static Map<String, Boolean> positions = new HashMap<>();
static {
//Initially all positions are free (so set to true)
positions.put("A", true);
positions.put("B", true);
}
public synchronized void occupyOrClear(String position,
boolean status) {
positions.put(position, status);
}
public boolean isClear(String position) {
return positions.get(position);
}
}
MyThread 類:
public class MyThread implements Runnable {
private String[] positions;
private String customer;
public MyThread(String customer, String[] positions) {
this.positions = positions;
this.customer = customer;
}
private Status status = new Status();
public void run() {
for (int i = 0; i < positions.length;) {
String position = positions[i];
if (status.isClear(position)) {
// position occupied now
status.occupyOrClear(position, false);
System.out.println(position + " occupied by :"+customer);
try {
//my real application logic goes below (instead of sleep)
Thread.sleep(2000);
} catch (InterruptedException inteExe) {
System.out.println(" Thread interrupted ");
}
// Now clear the position
status.occupyOrClear(position, true);
System.out.println(position + " finished & cleared by:"+customer);
i++;
} else {
try {
Thread.sleep(1000);
} catch (InterruptedException inteExe) {
System.out.println(" Thread interrupted ");
}
}
}
}
}
線程測試類:
public class ThreadTest {
public static void main(String[] args) {
String[] positions = { "A", "B"};
Status status = new Status();
Thread customerThread1 = new Thread(new MyThread(status, "customer1", positions));
Thread customerThread2 = new Thread(new MyThread(status, "customer2", positions));
Thread customerThread3 = new Thread(new MyThread(status, "customer3", positions));
customerThread1.start();
customerThread2.start();
customerThread3.start();
}
}
即使我使用了“同步”,我也可以注意到有時 Thread3 會在 Thread2 之前啟動,您能幫我解決這個問題並獲得以下結果嗎?
(1) 總是 customerThread1 應該先占位,然后是 customerThread2,然后是 customerThread3(等等......)
(2) 一旦customerThread1釋放了A的位置,customerThread2就應該立即拾取該位置(而不是customerThread2和customerThread3等待customerThread1完成所有位置)。並且一旦customerThread2完成位置'A',那么 customerThread3 應該把它撿起來,等等。
(3) 一旦位置(A、B 等)被釋放/可用,下一個 customerThread 應該立即拿起它。
(4) 解決方案應避免所有競爭條件
有幾個基本問題。
您已經破壞了代碼並且已經注意到它不起作用。 但是,您不是詢問如何修復損壞的代碼,而是要求具有更高性能的替代方案。 您將永遠無法以這種態度編寫工作程序。
顯然,您不知道synchronized
是做什么的。 它獲取只能由一個線程持有的特定對象實例的鎖。 因此,所有在同一對象上同步的代碼片段都被強制按順序執行,並具有必要的內存可見性。 所以你的代碼失敗有兩個原因:
Status
實例,訪問static
變量引用的相同對象。 由於所有線程使用不同的鎖,這種訪問是完全不安全的。occupyOrClear
被聲明為synchronized
,但你的方法isClear
不是。 因此,即使所有的線程使用了相同的鎖實例occupyOrClear
,結果isClear
因為它不安全的訪問地圖仍然是不可預知的。 你有表格的代碼if(status.isClear(position)) { status.occupyOrClear(position, false); …
與check-then-act反模式相匹配。 即使這兩個方法調用中的每一個都是線程安全的,這個順序仍然是不安全的,因為在這兩個調用之間,一切都可能發生,最值得注意的是,線程剛剛檢查的條件可能會在線程不注意的情況下發生變化。 因此,兩個或更多線程可以調用isClear
,接收true
,然后繼續執行occupyOrClear
。
您正在使用Thread.sleep
。
您可以嘗試使用以下偽代碼:
main() {
//some concurrent queues, eg ConcurrentLinkedQueue
Queue t1Tasks = new Queue("A","B","C");
Queue t2Tasks = new Queue();
Queue t3Tasks = new Queue();
Thread t1 = new PThread(t1Tasks,t2Tasks,"customer1");
Thread t2 = new PThread(t2Tasks,t3Tasks,"customer2");
Thread t3 = new PThread(t3Tasks,null,"customer3");
}
PThread {
Queue q1,q2;
PThread(Queue q1, Queue q2,...){}
run() {
while (item = q1.get()) {
//process item
q2.put(item); //to be processed by next thread
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.