【问题标题】:thread synchronization problem (with updating a variable sum) [duplicate]线程同步问题(更新变量总和)[重复]
【发布时间】:2018-09-20 05:28:28
【问题描述】:

当我想使用同步关键字或锁进行更新时,它在 sum 变量为 int 时有效,但在它为 Integer 对象时无效。

代码看起来像这样 -

public class TestSynchronized {
  private  Integer sum = new Integer(0);

  public static void main(String[] args) {
    TestSynchronized test = new TestSynchronized();
    System.out.println("The sum is :" + test.sum);
  }

  public TestSynchronized() {
    ExecutorService executor = Executors.newFixedThreadPool(1000);

    for (int i = 0; i <=2000; i++) {
      executor.execute(new SumTask());
    }

    executor.shutdown();

    while(!executor.isTerminated()) {
    }
  }

  class SumTask implements Runnable {
    Lock lock = new ReentrantLock();

    public void run() {
    lock.lock();

      int value = sum.intValue() + 1;
      sum = new Integer(value);

        lock.unlock(); // Release the lock
      }

  }
}

【问题讨论】:

  • Lock lock = new ReentrantLock(); 你正在为每个线程创建一个新对象
  • 对于这个用例,我建议使用AtomicIntegergetAndIncrementincrementAndGet。那么你就不再需要锁了。
  • 您的sum 的增量将更容易(并且等效地)写为sum++;(除了您有时会使用缓存的 Integer 实例)。自动装箱“免费”完成您在此处所做的工作。

标签: java multithreading synchronization


【解决方案1】:

问题是您为每个 SumTask 对象分隔了 locks。这些对象应该共享locks

TestSynchronized() 方法中创建一次lock 对象。这应该由所有new SumTask(lock) 对象共享。

所以你的SumTask 类看起来像:

class SumTask implements Runnable {
    Lock lock;

    public SumTask(Lock commonLock) {
        this.lock = commonLock;
    }

    public void run() {
        lock.lock();

        int value = sum.intValue() + 1;
        sum = new Integer(value);

        lock.unlock(); // Release the lock
    }

}

并且不要忘记在TestSynchronized() 方法中创建一个commonLock 对象:

  Lock lock = new ReentrantLock();

  executor.execute(new SumTask(commonLock));

【讨论】:

  • OP 说“当 sum 变量为 int 时它可以工作”我认为值得指出的是,这充其量只是侥幸。
猜你喜欢
  • 2021-09-21
  • 1970-01-01
  • 1970-01-01
  • 2017-04-10
  • 2016-09-11
  • 1970-01-01
  • 2016-04-04
  • 1970-01-01
相关资源
最近更新 更多