![](/img/trans.png)
[英]java - Own SeqLock implementation, would avoiding spinlock be better?
[英]Is it possible to efficiently implement a seqlock in Java?
另一个问题让我怀疑,是否可以使用Java中的易失性版本计数器有效地实现seqlock 。
这是一个典型的实现,对于这种情况,将永远只有一个编写器线程:
class Seqlock {
private volatile long version = 0;
private final byte[] data = new byte[10];
void write(byte[] newData) {
version++; // 1
System.arraycopy(newData, 0, data, 0, data.length); // 2
version++; // 3
}
byte[] read() {
long v1, v2;
byte[] ret = new byte[data.length];
do {
v1 = version; // 4
System.arraycopy(data, 0, ret, 0, data.length); // 5
v2 = version; // 6
} while (v1 != v2 || (v1 & 1) == 1);
}
}
基本思想是在写入之前和之后增加版本号,并通过验证版本号相同和偶数(奇数表示“正在进行写入”)来供读者检查是否获得“一致”读取。
由于版本易变,因此在编写者线程和阅读者线程中的关键操作之间存在各种事前发生的关系。
但是,我看不到是什么阻止了(2)处的写入向上移动到(1)以上,从而导致读者看到正在进行的写入。
例如,使用每行旁边的注释中的标签,以下易失性读写的同步顺序(还显示了非易失性的data
读和写,因此不属于同步顺序的一部分,缩进显示):
1a (version is now 1)
2a (not part of the synchronization order)
3 (version is now 2)
4 (read version == 2, happens before 3)
5 (not part of the synchronization order)
6 (read version == 2, happens before 4 and hence 3)
1b (second write, version is now 3)
2b (not part of the synchronization order)
根据ISTM,在5(读取数据)和2b(第二次写入数据)之间没有发生任何情况,因此2b可能在读取和读取错误数据之前发生。
如果是这样,是否write()
声明为synchronized
帮助?
在Java中,您可以非常简单地实现共享缓冲区(或其他对象):
public class SharedBuffer {
private volatile byte[] _buf;
public void write(byte[] buf) {
_buf = buf;
}
public byte[] read() {
// maybe copy here if you are worried about passing out the internal reference
return _buf;
}
}
显然,这不是“ seqlock”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.