我有一个遗留的伪码:
public class Wrapper {
private volatile Sink sink;
public synchronized void flushSink() {
if (sink != null) {
synchronized (sink) {
sink.flush();
}
}
}
public void close() throws IOException {
var sink = this.sink;
if (sink != null) {
sink.receivedLast();
}
}
}我的问题是关于嵌套的synchronized块。
据我所知,在这种情况下,上述块是多余的,就好像两个线程同时调用flushSink()一样,那么每次只有一个线程可以访问私有字段sink。因此,代码可以简化为
public class Wrapper {
private volatile Sink sink;
public synchronized void flushSink() {
if (sink != null) {
sink.flush();
}
}
}有可能进一步消除统治
public class Wrapper {
private volatile Sink sink;
public synchronized void flushSink() {
var sink = this.sink;
if (sink != null) {
sink.flush();
}
}
}因此,我的问题是,这种重构在同步和JMM方面是否正确?如果是的话(或者如果不是)--是否有基于JCStress的测试来证明它?
发布于 2022-11-25 16:49:03
据我所知,在这种情况下,
是多余的,就像两个线程并发调用flushSink()一样,一次只有一个线程可以访问私有字段接收器。因此,代码可以简化为
只要代码中没有其他地方可以在同步块中访问sink,那么这是多余的。
例如,如果close()方法更改为以下内容,
public void close() throws IOException {
var sink = this.sink;
if (sink != null) {
synchronized(sink) {
sink.receivedLast();
}
}
}这样,flushSink()中的同步块就不会无用,因为它将确保不同时调用receivedLast()和flush()。
https://stackoverflow.com/questions/74575037
复制相似问题