使用ConcurrentHashMap + synchronized + 類的isDestroy標記 完成線程安全的程序設計

import java.util.concurrent.ConcurrentHashMap;

class Room {
    public int roomId = 1;

    public boolean isDestroy = false;

    public int getRoomId() {
        return this.roomId;
    }

    public void subRoomId() {
        this.roomId--;
    }
}

public class Demo2 {
    public ConcurrentHashMap<Integer, Room> map = new ConcurrentHashMap<>();

    public Demo2() {
        map.put(1, new Room());
    }

    public static void main(String[] args) {
        Demo2 d = new Demo2();

        for (int i = 0; i < 500; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Room r = d.map.get(1);
                    if (r != null) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        // 1
                        synchronized (r) {
                            // 2.雖然多個線程爭奪到r後可以進來,但是每次只有一個線程爭奪得到r,當這個線程處理完r的isDestroy標記後,
                            // 後續的線程進來,一定會訪問到被銷燬了
                            if (!r.isDestroy) {

                                // 3 標記該房間已經銷燬
                                d.map.remove(1);

                                // 標記爲true,讓後面的無法標記
                                r.isDestroy = true;
                                System.out.println(Thread.currentThread().getName() + " remove roomId=" + r.getRoomId() + " " + r.toString());
                            }
                        }
                    }
                }
            }).start();
        }
    }
}

/*
Thread-4 remove roomId=1 Room@1c7a4fc
 */

雖然d.map是線程安全的類,但是500個線程順序訪問後,都得到了r,切判斷了r不爲null,從而都可以接着先後順序爭奪到r的鎖;

但是同一時刻卻只能有一個線程爭奪到r, 這時如果這個線程設置了r的標記爲已經銷燬,

那麼後續線程再進來也不會重複對房間對象Room操作了,所以就輸出了1次

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章