【问题标题】:The optimal way to lock and write to a file in Scala on Linux在 Linux 上的 Scala 中锁定和写入文件的最佳方法
【发布时间】:2018-04-10 15:55:35
【问题描述】:

我很难找到正确的方法来使用 Scala 在 Linux 上执行任何高级文件系统操作。

我真的不知道是否最好用以下伪代码来描述:

with fd = open(path, append | create):
    with flock(fd, exclusive_lock):
        fd.write(string)

基本上以附加模式打开一个文件(如果它不存在则创建它),获取它的独占锁并写入它(使用隐式解锁并随后关闭)。

如果我知道我的程序只能在 linux 上运行,是否有一种简单、干净和有效的方法? (最好不要粗略地提供应该处理的异常)。

编辑:

我得到的答案是,据我所见和测试是正确的。但是它非常冗长,所以我将其标记为正常,但我将这段代码的 sn-p 留在这里,这是我最终使用的代码(不确定它是否正确,但据我所知,它可以做所有事情我需要):

  val fc  = FileChannel.open(Paths.get(file_path), StandardOpenOption.CREATE, StandardOpenOption.APPEND)
  try {
    fc.lock()
    fc.write(ByteBuffer.wrap(message.getBytes(StandardCharsets.UTF_8)))
  } finally { fc.close() }

【问题讨论】:

  • 为什么需要锁定文件?什么problem 锁定了应该解决的文件?您无法保证任何底层文件系统都支持锁定。
  • "为什么需要锁定文件?"一般而言,需要锁定以确保可以“安全地”写入和读取由多个线程访问的资源,其中至少一个是写入器,也就是说,所有操作都是按顺序排列的。因此,假设我有一个进程 A 写入文件“X”,而进程 B 从同一个文件“X”读取,我需要锁定文件才能安全地使用它。
  • “你不能保证任何底层文件系统都支持锁定”,据我所知,大多数(阅读:所有)现代文件系统在网络文件系统之外都有一个有点兼容的文件锁定接口

标签: java linux scala file filesystems


【解决方案1】:

您可以使用FileChannel.lockFileLock 来获得您想要的:

import java.nio.ByteBuffer
import java.nio.channels.FileChannel
import java.nio.charset.StandardCharsets
import java.nio.file.{Path, Paths, StandardOpenOption}

import scala.util.{Failure, Success, Try}

object ExclusiveFsWrite {
  def main(args: Array[String]): Unit = {
    val path = Paths.get("/tmp/file")
    val buffer = ByteBuffer.wrap("Some text data here".getBytes(StandardCharsets.UTF_8))

    val fc = getExclusiveFileChannel(path)
    try {
      fc.write(buffer)
    }
    finally {
      // channel close will also release a lock
      fc.close()
    }

    ()
  }

  private def getExclusiveFileChannel(path: Path): FileChannel = {
    // Append if exist or create new file (if does not exist)
    val fc = FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.APPEND,
      StandardOpenOption.CREATE)
    if (fc.size > 0) {
      // set position to the end
      fc.position(fc.size - 1)
    }
    // get an exclusive lock
    Try(fc.lock()) match {
      case Success(lock) =>
        println("Is shared lock: " + lock.isShared)
        fc
      case Failure(ex) =>
        Try(fc.close())
        throw ex
    }
  }
}

【讨论】:

    猜你喜欢
    • 2021-09-08
    • 1970-01-01
    • 2011-05-16
    • 2010-09-15
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 2023-03-24
    相关资源
    最近更新 更多