首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我能消除同步方法中私有字段上嵌套的同步吗?

我能消除同步方法中私有字段上嵌套的同步吗?
EN

Stack Overflow用户
提问于 2022-11-25 15:39:02
回答 1查看 36关注 0票数 -1

我有一个遗留的伪码:

代码语言:javascript
复制
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。因此,代码可以简化为

代码语言:javascript
复制
public class Wrapper {
  private volatile Sink sink;

  public synchronized void flushSink() {
    if (sink != null) {
      sink.flush();
    }
  }
}

有可能进一步消除统治

代码语言:javascript
复制
public class Wrapper {
  private volatile Sink sink;

  public synchronized void flushSink() {
    var sink = this.sink;
    if (sink != null) {
      sink.flush();
    }
  }
}

因此,我的问题是,这种重构在同步和JMM方面是否正确?如果是的话(或者如果不是)--是否有基于JCStress的测试来证明它?

EN

回答 1

Stack Overflow用户

发布于 2022-11-25 16:49:03

据我所知,在这种情况下,

是多余的,就像两个线程并发调用flushSink()一样,一次只有一个线程可以访问私有字段接收器。因此,代码可以简化为

只要代码中没有其他地方可以在同步块中访问sink,那么这是多余的。

例如,如果close()方法更改为以下内容,

代码语言:javascript
复制
public void close()  throws IOException {
  var sink = this.sink;
  if (sink != null) {
    synchronized(sink) {
      sink.receivedLast();
    }
  }
}

这样,flushSink()中的同步块就不会无用,因为它将确保不同时调用receivedLast()flush()

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74575037

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档