【问题标题】:Java multithreading: redundant to use java.util.concurrent classes in a synchronized method?Java 多线程:在同步方法中使用 java.util.concurrent 类是多余的吗?
【发布时间】:2015-04-24 16:19:51
【问题描述】:

我有一个具有以下类级变量的类:

private LinkedBlockingQueue<Integer> inputQueue;
private StringBuffer textBuffer;
private int currentIndex;
private String[] p;
private List<String[]> pageList;
private int cursor;

该类有一个方法 setInput() 可以被多个线程访问。该方法像这样更改上述所有变量

public void setInput(String s) {
    p[cursor] = input;
    cursor++;
    if (cursor == 1000) {
        // UI logic
        textBuffer.setLength(0);
        p = new String[];
        cursor = 0;
    }
    // Some other logic here

    pageList.add(p);
    currentIndex++;
    if (!inputQueue.offer(currentIndex)) {
        throw new RuntimeException();
    }        
}

这些变量可以被类中的其他代码sn-p读取,但只能在setInput()中修改。并且该类中的所有其他方法都没有线程安全问题。换句话说,它们保证被主线程调用。在这种情况下,如果我将 synchronized 关键字放在方法 setInput() 之前,那么我需要使用 java.util.concurrent 中的 LinkedBlockingQueue 吗?当方法同步时,这些变量是否保证是线程安全的?谢谢。

【问题讨论】:

  • 请使用 StringBuilder 而不是 StringBuffer,因为它在十年前被替换。没有外部同步,几乎不可能正确使用 StringBuffer。
  • 什么代码从 inputQueue 中提取数据?这会影响它是否需要并发。
  • 谢谢你的意见。是的,轮询操作是在主线程中完成的,而不是在这个方法中。所以这里需要一个并发队列。谢谢。
  • 为什么你把一个 int 放在队列中,而不是你的类?您是否考虑过每次都创建一个新的 YourClass(可能是不可变的)并将它们放入队列中? (必须声明为静态或在您的类之外)这就是我通常使用队列的方式。但显然我不明白你的应用和要求!

标签: java multithreading concurrency


【解决方案1】:

为了线程安全,所有访问字段的方法(读取和写入)都应该是synchronized

【讨论】:

    【解决方案2】:

    不,在您的场景中,使用 setInput 方法 synchronized 是不够的。 所有 访问变量的方法需要同步,只读取变量的方法也需要同步,否则可能会在setInput 执行时读取变量,因此您可能会看到对象的不一致状态。

    如果很多线程正在读取变量但只有少数线程正在写入它们,那么使读取方法也synchronized 可能是不必要的性能瓶颈。在这种情况下,最好使用ReadWriteLock,这样所有读取线程都可以同时访问该对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-15
      • 1970-01-01
      • 1970-01-01
      • 2012-11-22
      • 2013-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多