Java mmap缓冲区内存模型

时间:2018-08-02 07:07:42

标签: java mmap java-memory-model

假定两个线程同时使用单个内存映射的缓冲区(java.nio.channels.FileChannel.map())。

第一个线程是:

  • 写记录的大小;
  • 自己写记录;
  • 重复。

例如

ByteBuffer buffer = channel.map(READ_WRITE, 0, ...)

buffer.putShort((short) data.length);
buffer.put(data);

读取线程正在读取这些数据包:

short size = buffer.getShort();
byte[] bytes = new byte[size];
buffer.get(bytes);

我有时会从BufferUnderflowException那里得到buffer.get(bytes),这是合理的,因为在此幼稚的代码中显然存在种族。读取可能会在写入大小之后但在发送数据包之前发生。

问题是,写入mmap缓冲区是否易失吗?我可以安全地解决此问题,而只是在写线程中重新排序写操作,这样在包本身或某些包之前就看不到包的长度了应该使用外部协调机制吗?

1 个答案:

答案 0 :(得分:0)

这里没有与ERROR Error: Uncaught (in promise): TypeError: undefined is not a function TypeError: undefined is not a function at Array.map (<anonymous>) at webpackAsyncContext (eval at ./src/$$_lazy_route_resource lazy recursive (main.bundle.js:20), <anonymous>:302:34) at SystemJsNgModuleLoader.loadAndCompile (core.js:6558) at SystemJsNgModuleLoader.load (core.js:6542) at RouterConfigLoader.loadModuleFactory (router.js:4543) at RouterConfigLoader.load (router.js:4523) at MergeMapSubscriber.eval [as project] (router.js:2015) at MergeMapSubscriber._tryNext (mergeMap.js:128) at MergeMapSubscriber._next (mergeMap.js:118) at MergeMapSubscriber.Subscriber.next (Subscriber.js:92) at Array.map (<anonymous>) at webpackAsyncContext (eval at ./src/$$_lazy_route_resource lazy recursive (main.bundle.js:20), <anonymous>:302:34) at SystemJsNgModuleLoader.loadAndCompile (core.js:6558) at SystemJsNgModuleLoader.load (core.js:6542) at RouterConfigLoader.loadModuleFactory (router.js:4543) at RouterConfigLoader.load (router.js:4523) at MergeMapSubscriber.eval [as project] (router.js:2015) at MergeMapSubscriber._tryNext (mergeMap.js:128) at MergeMapSubscriber._next (mergeMap.js:118) at MergeMapSubscriber.Subscriber.next (Subscriber.js:92) at resolvePromise (zone.js:809) at resolvePromise (zone.js:775) at eval (zone.js:858) at ZoneDelegate.invokeTask (zone.js:421) at Object.onInvokeTask (core.js:4740) at ZoneDelegate.invokeTask (zone.js:420) at Zone.runTask (zone.js:188) at drainMicroTaskQueue (zone.js:595) 相关的内容。您只有两个写入,它们必须是原子的。我不知道重新排序写操作将如何解决任何问题,而volatile不会使事情变得原子化。

您需要确保在写入标头和数据之前无法执行读取操作,因此您需要为此进行外部同步。

还值得注意的是,volatile在很大程度上取决于基础文件系统和操作系统,因此最好确保您没有编写依赖于本机行为的易碎代码。