簡體   English   中英

如何實現多個線程安全的讀/寫鎖(ConcurrentHashmap)

[英]How to implement multiple threadsafe read/write locks (ConcurrentHashmap)

我有一個讀取和寫入大量文件的應用程序。 目的是防止在另一個線程寫入特定文件時讀取或寫入該文件。 我不想在寫入單個文件時鎖定所有文件的讀寫,因為這會導致不必要的鎖定。

為了實現這一目標,我將並發HashMap與同步化塊結合使用,但是如果有更好的解決方案,我可以接受。

這是粗略的代碼。

private static final ConcurrentMap<String, String> lockMap = new ConcurrentHashMap();


private void createCache(String templatePath, String cachePath){

//get template 
String temp = getTemplate(templatePath);

String myRand = randomString();
lockMap.put(cachePath,myRand);

// save cache file
  try {
    // ** is  lockMap.get(cachePath) still threadsafe if another thread has changed the row's value?
    synchronized ( lockMap.get(cachePath) ){
      Files.write(Paths.get(cachePath),temp.getBytes(StandardCharsets.UTF_8));
    }
  } finally {
    // remove lock if not locked by another thread in the meantime
    lockMap.remove(cachePath, myRand);
  }

}


private String getCache(String cachePath){

 String output = null;

  //only lock if this specific file is being written at the moment
  if ( lockMap.contains(cachePath) ){
        synchronized ( lockMap.get(cachePath) ){
            output = getFile(cachePath);
        }
    } else {
        output = getFile(cachePath);
    }

  return output;

}

// main event        
private String cacheToString (String templatePath, String cachePath){

  File cache = new File(cachePath);

  if ( !cache.exists() ){
    createCache(templatePath, cachePath)
  }

  return getCache(cachePath);

}

我遇到的問題是,盡管該線程僅在另一個線程未更改所請求文件的鎖的情況下才將其刪除,但另一個線程仍可能為該條目更新lockMap中的值-如果發生這種情況,同步是否會失敗?

我每次都會寫一個新的臨時文件,並在完成后將其重命名。 重命名是原子的。

// a unique counter across restarts
final AtomicLong counter = new AtomicLong(System.currentTimeMillis()*1000);

private void createCache(String templatePath, String cachePath) {
    //get template
    String temp = getTemplate(templatePath);

    Path path = Paths.get(cachePath);
    Path tmpPath = Paths.get(path.getParent().toString(), counter.getAndIncrement() + ".tmp");
    // save cache file
    Files.write(tmpPath, temp.getBytes(StandardCharsets.UTF_8));
    Files.move(tmpPath, path, ATOMIC_MOVE, REPLACE_EXISTING);
}

如果多個線程嘗試寫入同一文件,則執行move的最后一個線程move獲勝。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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