簡體   English   中英

有什么有效的方法可以將線程鎖定為僅同時對每個文件進行鎖定,而不僅僅是對任何文件操作進行寫入?

[英]What is efficient way to lock threads from simultaneous ONLY per file, not just write to any file operation?

考慮一些瑣碎的場景。 我們有一些游戲,其中每個玩家都由一個線程代表。 我們的服務器很脆弱,經常由於上帝的行動而死掉,因此,如果服務器發生故障,我們需要保持游戲會話的狀態。 我們不能僅僅因為喜歡讓生活變得過於復雜而使用數據庫。

因此,我嘗試在本練習中變得新穎:

  • 每個新游戲會話均以隨機生成的UUID文件名保存在文件中。
  • 游戲會話修改(用戶動作)被保存在與游戲會話相對應的文件中。
  • 10個具有20個用戶的游戲= 10個具有隨機UUID生成名稱的文件

現在的問題是:在全局上下文中同步寫入非常容易,即只有一個線程可以寫入/覆蓋文件。 這意味着,在第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.

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