简体   繁体   English

如何实现多个线程安全的读/写锁(ConcurrentHashmap)

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

I have an application which reads and writes a number of files. 我有一个读取和写入大量文件的应用程序。 The aim is to prevent a specific file from being read or written while it is being written by another thread. 目的是防止在另一个线程写入特定文件时读取或写入该文件。 I do not want to lock the reading and writing of all files while a single file is being written as this causes unnecessary locking. 我不想在写入单个文件时锁定所有文件的读写,因为这会导致不必要的锁定。

To try and achieve this I am using a concurrentHashMap in conjunction with a synchonized block, but if there is a better solution I am open to it. 为了实现这一目标,我将并发HashMap与同步化块结合使用,但是如果有更好的解决方案,我可以接受。

Here is the rough code. 这是粗略的代码。

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);

}

The problem I have is that although the thread will only remove the lock for the requested file if it's unchanged by another thread, it's still possible for another thread to update the value in the lockMap for this entry - if this happens will the synchronisation fail? 我遇到的问题是,尽管该线程仅在另一个线程未更改所请求文件的锁的情况下才将其删除,但另一个线程仍可能为该条目更新lockMap中的值-如果发生这种情况,同步是否会失败?

I would write a new temporary file each time and rename it when finished. 我每次都会写一个新的临时文件,并在完成后将其重命名。 Renaming is atomic. 重命名是原子的。

// 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);
}

If multiple threads try to write to the same file, the last one to perform a move wins. 如果多个线程尝试写入同一文件,则执行move的最后一个线程move获胜。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM