gpt4 book ai didi

java - 操作系统范围同步访问 MappedByteBuffer

转载 作者:行者123 更新时间:2023-11-30 04:05:55 28 4
gpt4 key购买 nike

我可以让 2 个 Java 进程通过 MappedByteBuffer 共享一个内存区域。

但是,如果这两个进程可以同时读取或写入偏移量x(从共享内存开始处)的字节,我如何同步对该字节的访问?

这是所需用法:

假设:每个进程只有 1 个线程尝试读写访问。

                           |
========================== | ============================
Process A | Process B
========================== | ============================
|
lock(sharedMemory[x]); | lock(sharedMemory[x]); (Line 1.)
... | ...
// read from byte at x | // write to byte at x
a = sharedMemory[x]; | sharedMemory[x] = b;
... | ...
unlock(sharedMemory[x]); | unlock(sharedMemory[x]); (Line 20.)
========================== | ============================
|

时间在上图中向下流动。

因此,在给定时间只有进程 A 或进程 B(但不能同时执行两者)可以执行第 1 行到第 20 行。

最佳答案

Java 中没有执行此操作的标准方法。您可以尝试做的是使用 Unsafe 创建您自己的锁,就像我在这个库 AbstractByte in OpenHFT/Java-Lang 中所做的那样请参阅 tryLock、busyLock、unlock 方法。

我还没有测试它跨进程的效果如何。目前我只有一个进程写入。

如果您有一名写入者和一名读取者,则无需锁定记录。您可以使用内存屏障或时间戳保护。

一个简单的时间戳保护可以像这样工作。

作者:

- on start, 
- if even, increment to odd with memory barriers.
- if odd, retry until even.
- perform multiple writes
- on finish, increment the counter to an even number

读者:

- on start, (with a read barrier)
- if even, take a copy of the counter.
- if odd, retry until even.
- read the multiple values.
- read the counter again, if the counter changed, loop until it doesn't.

当然,如果您有单个值,则只需要有序写入和 volatile 读取,因此根本不需要锁定。

<小时/>

编辑:我添加了一个示例 LockingViaMMapMainLockingViaFileLockMain这使用两个进程来锁定共享内存映射文件中的记录。第一个进程锁定并将标志设置为 false(仅当为 true 时),第二个进程将标志设置为 true(仅当为 false 时)

这两个过程打印在我的笔记本电脑上

Toggled 10,000,128 times with an average delay of 31 ns

作为比较,使用 FileLock 的基准看起来像

Toggled 10,000,128 times with an average delay of 2,402 ns

FileLock 速度非常快,为 2.4 微秒,但在我的计算机上使用文件中的单独锁定速度快了 80 倍。

如果 FileLock 足够快,您应该使用它,因为

  • 它不会更改文件。
  • 如果进程终止,锁会自动释放。
  • 它应该适用于网络安装的文件系统。我不希望内部锁在系统之间起作用。

有趣的代码读取

File tmpFile = new File(System.getProperty("java.io.tmpdir"), "lock-test.dat");
FileChannel fc = new RandomAccessFile(tmpFile, "rw").getChannel();
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, RECORDS * RECORD_SIZE);
ByteBufferBytes bytes = new ByteBufferBytes(mbb.order(ByteOrder.nativeOrder()));


// the lock and toggle.
bytes.busyLockLong(recordOffset + LOCK);
try {
boolean flag = bytes.readBoolean(recordOffset + FLAG);
if (flag == toggleTo) {
if (t % 100 == 0)
System.out.println("j: " + j + " is " + flag);
continue;
}
bytes.writeBoolean(recordOffset + FLAG, toggleTo);
break;
} finally {
bytes.unlockLong(recordOffset + LOCK);
}

关于java - 操作系统范围同步访问 MappedByteBuffer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20726764/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com