[英]What is efficient way to lock threads from simultaneous ONLY per file, not just write to any file operation?
考慮一些瑣碎的場景。 我們有一些游戲,其中每個玩家都由一個線程代表。 我們的服務器很脆弱,經常由於上帝的行動而死掉,因此,如果服務器發生故障,我們需要保持游戲會話的狀態。 我們不能僅僅因為喜歡讓生活變得過於復雜而使用數據庫。
因此,我嘗試在本練習中變得新穎:
現在的問題是:在全局上下文中同步寫入非常容易,即只有一個線程可以寫入/覆蓋文件。 這意味着,在第10個游戲中的第1個狀態保持不變的同時,其他9個游戲會話的線程(玩家)也在等待保持其自己的狀態。
如何確保只有相同的游戲會話線程才能相互阻止寫入同一文件,但是對應於不同游戲會話的2個線程可以同時寫入兩個文件?
正如我所做的調查一樣,FileLock是用於進程間鎖定的-不是線程間的,因此這里沒有幫助。
唯一明顯的解決方案似乎是對UUID字符串進行同步,這樣,當線程在同一UUID字符串上創建/讀取/寫入時,我會獲得鎖定。
這種方法有什么風險? 如果我保證字符串對於這些操作非常獨特:“ game_session_identifier_” + UUID應該可以正常工作,並且不會意外鎖定其他東西。 我對嗎?
為每個文件同步Semaphore
private Map<String, Semaphore> semaphores = new ConcurrentHashMap<>();
然后在您的代碼中:
Semaphore semaphore = semaphores.computeIfAbsent(filename, () -> new Semaphore(1, true));
semaphore.acquireUninterruptibly();
// write to file
semaphore.release();
您必須為此添加更多代碼,最后進行阻止,以確保您不會進入阻止狀態,但這是該方法的本質。
您可以使用java.util.concurrent包中的信號燈。 每個游戲都有自己的寫操作信號燈(例如),因此當一個線程開始向文件寫入smth時,他獲取了該信號燈,此游戲中的另一個線程將等待直到第一個線程完成。
您的方法似乎是正確的,但解決方案的簡化版本是擁有一個文件來鎖定地圖。
Map<Path, Lock> locks = ... a lock per file;
void writeData(path Path, byte[]data){
Lock lock = Objects.requireNonNull(locks.get(path));
try{
lock.lock();
//write data
}finally{
lock.unlock();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.