Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 操作系统范围内对MappedByteBuffer的同步访问_Java_Shared Memory_Synchronize - Fatal编程技术网

Java 操作系统范围内对MappedByteBuffer的同步访问

Java 操作系统范围内对MappedByteBuffer的同步访问,java,shared-memory,synchronize,Java,Shared Memory,Synchronize,我可以通过MappedByteBuffer让两个Java进程共享一个内存区域 但若这两个进程可以同时读取或写入偏移量x(从共享内存的开始)处的字节,那个么如何同步对该字节的访问 以下是所需的用法: 假设:每个进程只有1个线程将尝试读写访问 在上图中,时间向下流动 因此,在给定的时间内,只有进程A或进程B(但决不能同时执行这两个进程)可以执行第1行到第20行。在Java中没有标准的执行方法。您可以尝试使用不安全的方法来创建自己的锁,就像我在这个库中所做的一样。请参阅tryLock、busyLock

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

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

以下是所需的用法:

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

在上图中,时间向下流动


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

在Java中没有标准的执行方法。您可以尝试使用不安全的方法来创建自己的锁,就像我在这个库中所做的一样。请参阅tryLock、busyLock和unlock方法

我还没有测试它在不同进程中的工作情况。目前我只有一个写作过程

如果您有一个writer和一个reader,则不需要锁定记录。您可以使用内存屏障或时间戳保护

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

作者:

- 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.
当然,如果您只有一个值,那么您只需要一个有序写入和一个易失性读取,这样就根本不需要锁定


编辑:我添加了一个示例,它使用两个进程来锁定共享内存映射文件中的记录。一个进程锁定并将标志设置为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);
}

似乎您正在尝试有效地重新实现IPC。多年来,操作系统为IPC提供了各种有用的机制,其中一些机制没有遇到这个问题。你确定需要在这里重新发明轮子吗?我的问题中有一个非常重要的关键词:Java。是的,Java可以调用本机库。Java还支持著名的IPC机制,TCP/IP套接字。您可以使用文件锁:独占锁用于写入,共享锁用于读取。@SamiKorhonen嗯,现在我为什么没有想到?!:-)请考虑把你的评论作为回答。我将评估它相对于彼得的,并将选择更简单的选择(几天后)。谢谢@当您构建自己的锁定结构时,需要使用Harry内存屏障。如果您使用synchronized和Lock,这些会为您消除内存障碍,但是进程之间没有任何有效的东西,所以您必须自己完成。算法似乎被破坏了。读者有可能在作者执行最后的反增量之前完成。@SamiKorhonen谢谢,我遗漏了一些细节。这也适用于多个写入程序。@Harry如果您想锁定整个文件,并且不太关心性能,那么这也可以。FileLock具有以下优点:;它不会改变文件,如果进程在持有锁时死亡,它会自动释放,它应该在网络文件系统上工作,代码应该更干净。@Harry我为FileLock添加了一些性能数字以及使用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);
}