我知道在轻松写入文件时会进行同步,但是问题是当有多个文件时,我们要对每个文件进行同步。我编写了这样的代码,使人们容易理解我所说的话
import java.io._
import java.util.concurrent.{ConcurrentHashMap, ConcurrentMap}
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
object Main {
val lock: ConcurrentMap[String, Boolean] = new ConcurrentHashMap[String, Boolean]()
def writeToFile(path: String): Unit = {
while (lock.get(path)) {}
lock.put(path, true)
println("write to file " + path)
Thread.sleep(2000)
lock.remove(path)
}
def main(args: Array[String]): Unit = {
Future {
writeToFile("1")
}
Future {
writeToFile("1")
}
Future {
writeToFile("1")
}
while (true) {}
}
}
结果将是:
write to file 1 [sleep 2 seconds]
write to file 1
write to file 1
最后两行同时打印。还有其他解决方案,请告诉我:)谢谢!!!
答案 0 :(得分:0)
您的操作未正确锁定或原子锁定。虽然一个线程可能刚刚从地图上删除了锁,但是其他两个线程可能同时退出各自的while循环。
此外,空的无限while循环会对您的资源造成不必要的负担。
我将您的锁映射替换为对每个路径都保留Future
的映射。该地图仅通过其原子compute
方法进行更新。如果在获得null
并创建我们的第一个写入前途之前从未写过路径。另一方面,如果该路径之前已写入,则可以链接新的写入操作。我已经使用.map
进行了此操作,如果需要,可以进行错误处理。
有关.map
与.andThen
的更多信息,请参见SO: future chaining
import java.util.concurrent.{ConcurrentHashMap, ConcurrentMap}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
object concurrent {
val writeOperations: ConcurrentMap[String, Future[_]] = new ConcurrentHashMap[String, Future[_]]()
def writeToFile(path: String): Unit = {
val writeOp = writeOperations.compute(path, (path, future) => {
if (future == null) {
Future {
println("write to file " + path)
Thread.sleep(2000)
}
} else {
future.map(x => { // you can use x for error handling of previous write operation
println("write to file " + path)
Thread.sleep(2000)
})
}
})
}
def main(args: Array[String]): Unit = {
val futures = Seq(
Future {
writeToFile("1")
}, Future {
writeToFile("1")
}, Future {
writeToFile("1")
}
)
futures.foreach(Await.ready(_, Duration.Inf))
writeOperations.values().forEach( x => Await.ready(x, Duration.Inf))
}
}