防止在多线程上下文中使用非线程安全方法

时间:2012-07-31 16:05:38

标签: java multithreading thread-safety

当用户尝试在多线程上下文中使用类的非线程安全方法时,是否有办法抛出异常?我想问题主要是检测多个线程正在尝试使用该方法。或者,我可以在函数声明中使用“not_synchronous”关键字/标记吗?

4 个答案:

答案 0 :(得分:3)

您可以在允许线程运行之前检查该方法是否已被使用 - 但这与使用锁定没有什么不同(注意:我的示例不是可重入的):

private static final AtomicBoolean used = new AtomicBoolean();

public static void unsafe() throws InterruptedException {
    if(!used.compareAndSet(false, true)) {
        throw new IllegalStateException();
    }
    //do you stuff
    used.set(false);
}

答案 1 :(得分:2)

没有简单的方法可以做到这一点,不。如果您检测到多个线程正在使用某个方法,那么您可能必须使用线程安全集合等。如果您正在做所有这些,那么您可能必须使该方法本身是线程安全的。

答案 2 :(得分:1)

扩展Gray的答案:假设您想要这样做(检测多个线程何时使用某个方法)。这种实现的天真(和不正确)可能如下所示:

volatile boolean methodBeingUsed = false;
public void doSomething() {
  if (methodBeingUsed) throw new IllegalStateException("You can't do that!");
  try {
    methodBeingUsed = true;
    // do something...
  } finally {
    methodBeingUsed = false;
  }
}

好吧,好吧......但是两个线程都可以通过第一次if (methodBeingUsed)检查并同时进入关键部分。所以现在我们可能会尝试添加一个锁以保护methodBeingUsed标志:

Lock methodLock = new ReentrantLock();
volatile boolean methodBeingUsed = false;
public void doSomething() {
  try {
    lock.lock();
    if (methodBeingUsed) throw new IllegalStateException("You can't do that!");
    methodBeingUsed = true;
  } finally {
    lock.unlock();
  }

  try {
    // do something...
  } finally {
    try {
      lock.lock();
      methodBeingUsed = false;
    } finally {
      lock.unlock();
    }
  }
}

当然,这假设doSomething()不能递归调用自身。如果可以,那么你还必须跟踪调用线程。添加一些更多的检查来解释我现在没想到的其他条件,并且很容易看到花费同步逻辑来检测多个线程使用的方法的工作将更好地花费在制作方法线程上 - 安全开始。

答案 3 :(得分:0)

实际上,如果您的目标是确定“多个线程正在尝试使用此方法”,并且您并未将其限制为“多个方法......同时” - 那么(原谅我)Alex的代码可以很好地适应:

  1. methodBeingUsed更改为threadOwningMethod,并将其设置为主题而不是true

  2. 您最后无需清除它 - 保存这些锁定/解锁步骤。一旦它拥有,它就拥有(资本主义猪!!)。

  3. 可以预先检查
  4. threadOwningMethod以查看它是否与当前线程(A-OK)匹配(抛出异常)而不必发生锁定。如果未设置(null),则会产生一次性命中:check / lock / check& set / unlock;这是安全的,因为threadOwningMethod标记为易失性。