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次