5

我有两种方法:a()b(). 虽然我对多个线程同时访问任何方法感到满意(这是可取的),但我不希望任何线程在执行时a()进入b()。我怎么做?

编辑 1

假设有 4 个线程并且Thread 1正在访问A(). 我想要的是所有 4 个线程都不应该使用B().

4

3 回答 3

6

检查底部的更新- 我认为这种方法行不通。留下它以供参考。


您可以使用信号量

  • 如果一个线程在 中b(),则试图执行的线程a()将阻塞,直到 的执行b()结束。
  • 如果一个线程在b()并且第二个线程尝试运行b(),它将能够
  • 如果 2 个线程a()b()未执行的情况下执行,则两者都将运行

注意:一旦一个线程进入a()并通过了“信号量测试”,另一个线程可以b()在结束前开始运行a()

该原理应该有效,但我尚未对其进行测试。

private final Semaphore inB = new Semaphore(1);

public void a() throws InterruptedException {
    inB.acquire(); //blocks until no thread is in b any longer
    //now we are good to go and execute a()
    //release the semaphore immediately for other threads who want to run a()
    inB.release(); 
    //rest of your code here
}
public void b() {
    //does not block to allow 2 thread running b() simultaneously
    boolean needToRelease = inB.tryAcquire(); 
    //rest of your code
    //if the permit was acquired, release it to allow threads to run a()
    if (needToRelease) {
        inB.release();
    }
}

编辑

您的意图尚不清楚,并且您的问题已被编辑,因为您的评论之一说您希望a()并且b()相互排斥(许多线程可以并行运行a()或并行运行,b()但绝不应该并行运行)。在这种情况下,您可以对 2 个信号量和.a()b()inAinB


更新 => 错误

正如@yshavit 在对另一个答案的评论中指出的那样,在以下情况下,代码中存在竞争条件:

  • T1运行a()并获取inB
  • T2 运行b()但获取失败inB
  • T1 版本inB
  • 尽管 T2 正在运行,但T3 运行a()并设法获取inBb()

似乎仅使用 Sempahores 无法实现这一点。这个答案提供了一个更好的解决方案。

于 2012-11-10T09:14:50.433 回答
3

为简单起见省略了异常处理:

public class Test {
  private final Object lock = new Object();
  private int counterA;
  private int counterB;

  public void a() {
    synchronized(lock) {
      while(counterB > 0) {
        lock.wait();
      }
      ++counterA;
    }

    // do work

    synchronized(lock) {
      --counterA;
      lock.notifyAll();
    }
  }

  public void b() {
    synchronized(lock) {
      while(counterA > 0) {
        lock.wait();
      }
      ++counterB;
    }

    // do work

    synchronized(lock) {
      --counterB;
      lock.notifyAll();
    }
  }
}
于 2012-11-10T09:37:56.660 回答
1

java.util.concurrent.locks是一个包含多个锁的 Java 包

in a(),取一个锁并在结束时释放它a()

in b(), 对同一个锁做同样的事情

如果您想处理不对称行为,您可以使用ReadWriteLock, a() 是读取器, b() 是写入器:几个 b() 锁,但几个 a() 没有。

于 2012-11-10T09:22:40.093 回答