【问题标题】:Synchronization syntax for access to concurrent collection访问并发集合的同步语法
【发布时间】:2017-10-08 15:30:43
【问题描述】:

我有以下代码:

public class State {
    private List<Position> m_track;

    public State() {
        m_track = Collections.synchronizedList(new ArrayList<Position>());
    }

    public List<Position> getTrack() {
        return m_track;
    }
}

// in different class
public void modifyTrack(State _state) {
    List<Position> local_track = _state.getTrack();
    synchronized (local_track) {
        // safely modify track
    }
}

但是Android Studio在线synchronized (local_track)给了我一个警告:

本地变量“local_track”报告的同步 局部变量或参数的同步。

当使用这种同步时,很难保证正确性。

可以通过控制访问来改进这样的代码,例如同步包装类,或通过在字段上同步。

如果我用synchronized (_state.getTrack()) 替换synchronized (local_track),警告就会消失。

如果我理解正确,我的local_track 只是一个引用,没有创建新对象,如果是这样,为什么我不能同步它?

【问题讨论】:

  • 忽略它。它不知道它在说什么。
  • @EJP,非常感谢
  • 阅读 Java 命名约定。 "" 仅适用于 SOME_CONSTANT。您不会在其他任何地方使用它。大多数 Java 编码风格指南也不鼓励使用“m”来表示“它是一个字段”。

标签: java multithreading android-studio synchronization


【解决方案1】:

我同意 EJP 的评论 - 在这种情况下,忽略它的“多线程”方面的警告是安全的。

但是:我仍然认为警告是“不良做法”的症状。您会看到:您将该列表外部化给您的Stateclass 的用户;更糟糕的是:然后那个用户类锁定在那个列表上;然后可能会修改它。

这与优秀的 OO 正好相反。您将内部实现细节公之于众;你甚至打算修改那个内部数据结构!

在我看来,这违反了各种原则,例如TDA 或简单的“信息隐藏”。

因此:响应此警告;您可能想退后一步,更仔细地查看您的设计;例如,看看是否有办法让 State 类对其轨道列表进行这些修改!

【讨论】:

  • 哎呀,实际上,而不是“安全修改轨道”注释应该是“安全迭代轨道”:) 这样它看起来像是一个可以容忍的设计解决方案
  • 即便如此:锁定那个东西对我来说看起来“错误”。您可以改为查看 here 并使用不同类型的列表,使其 安全 对其进行迭代。
  • 好吧,我用CopyOnWriteArrayList 替换了Collections.synchronizedList,这似乎是更简单和好看的解决方案,感谢您的输入和链接
  • 不客气!很高兴我能告诉你的不仅仅是“忽略它”;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-03
  • 2020-07-22
  • 2012-01-05
  • 1970-01-01
  • 2012-12-16
相关资源
最近更新 更多