【问题标题】:Avoid synchronized block for boolean flip避免布尔翻转的同步块
【发布时间】:2019-02-14 09:22:07
【问题描述】:

我有这个方法:

  public void lock(Asyncc.IAsyncCallback<Unlock, Object> cb) {

    synchronized (this) {
      if (this.locked) {
        this.queue.add(cb);
        return;
      }

      this.locked = true;
    }

    cb.done(null, this.makeUnlock(true));

  }

我可以使用一些技巧来避免调用 synchronized() 吗?

我相信分配一个布尔值是原子的,所以一次只有一个线程可以做到这一点。

我们的想法是避免 2 个线程获取锁。我们也不希望两个不同的代码路径获取锁,即使它们在同一个线程中。

【问题讨论】:

  • Asyncc.IAsyncCallback, cb.done, this.makeUnlock - 这不是标准的 java。请添加适当的标签。
  • “我们要避免2个线程获取锁”——除了获取锁的线程之外,还必须存在释放锁的线程,这也可能是争用的来源。请出示其代码。
  • 没错,当锁被释放时,可能会出现与获取锁时类似的同步问题。这是一个类似的问题,让我们只关注获取锁,因为它的概念相同
  • 我不确定你想要什么,但听起来你想要实现像互斥锁或信号量这样的同步机制。如果这是真的,那么它不仅仅是简单的“翻转布尔值”。 I believe assigning a boolean is atomic, so only one thread can do it at a time. - 接近事实(使用AtomicBoolean,正如@Kuikiker 所建议的那样,它确实是正确的)。但尚不清楚这种替换是否正确。例如。 this.queue.add(cb); 可以与 this.locked = true; 在其他线程中同时调用。我们需要看到更多的代码和解释。
  • 访问共享资源的所有线程必须遵守任何线程间通信措施。因此,仅显示一个部分的问题,例如添加到队列并将标志设置为 true,省略其他部分,例如从队列中取出元素和/或将标志设置为 false,是无法回答的。

标签: java concurrency


【解决方案1】:

一种潜在地加速它的方法是执行以下操作:

  public void lock(Asyncc.IAsyncCallback<Unlock, Object> cb) {

    boolean add = false;
    synchronized (this) {
      if (this.locked) {
        add = true;
      }
      else {
        this.locked = true;
      }
    }

    if(add){
      this.queue.add(cb);
      return;
    }

    cb.done(null, this.makeUnlock(true));

  }

但我还是不知道有没有办法避免同步阻塞。

【讨论】:

  • 这是错误的:2 个队列可能会同时干扰this.queue.add(cb)
  • 如果我锁定了this,它也会锁定this.queue,tmk?
  • @AlexeiKaigorodov 看这里:stackoverflow.com/questions/54626010/…
  • 您在任何同步语句或方法之外编写了this.queue.add(cb),因此引用的问题与您的代码无关。
  • this.queue是指位于堆中的对象,而不是栈,并且可以从不同的线程访问,所以必须用synchronized语句保护它,但不是。
【解决方案2】:

也许可以通过使用AtomicBoolean而不是布尔值来避免同步块

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2014-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-30
  • 2021-11-09
  • 1970-01-01
  • 2012-12-08
相关资源
最近更新 更多