簡體   English   中英

java線程替代同步

[英]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) 解決方案應避免所有競爭條件

有幾個基本問​​題。

  1. 您已經破壞了代碼並且已經注意到它不起作用。 但是,您不是詢問如何修復損壞的代碼,而是要求具有更高性能的替代方案。 您將永遠無法以這種態度編寫工作程序。

  2. 顯然,您不知道synchronized是做什么的。 它獲取只能由一個線程持有的特定對象實例的鎖。 因此,所有在同一對象上同步的代碼片段都被強制按順序執行,並具有必要的內存可見性。 所以你的代碼失敗有兩個原因:

    1. 您正在創建多個Status實例,訪問static變量引用的相同對象。 由於所有線程使用不同的鎖,這種訪問是完全不安全的。
    2. 你的occupyOrClear被聲明為synchronized ,但你的方法isClear不是。 因此,即使所有的線程使用了相同的鎖實例occupyOrClear ,結果isClear因為它不安全的訪問地圖仍然是不可預知的。
  3. 你有表格的代碼
    if(status.isClear(position)) { status.occupyOrClear(position, false); …
    check-then-act反模式相匹配。 即使這兩個方法調用中的每一個都是線程安全的,這個順序仍然是不安全的,因為這兩個調用之間,一切都可能發生,最值得注意的是,線程剛剛檢查的條件可能會在線程不注意的情況下發生變化。 因此,兩個或更多線程可以調用isClear ,接收true ,然后繼續執行occupyOrClear

  4. 您正在使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM