2

我有一个应用程序应该(在某些情况下)防止多线程。为了对此进行测试,我需要同时从多个线程调用一个方法。

class MyObject {

  val myMethodCalled = new AtomicBoolean()   

  def myMethod() = {

    if (myMethodCalled.getAndSet(true))
      throw new IllegalStateException("Do not call myMethod twice")
  }
}

我想从测试用例触发上述方法中的异常。

这可能JVM吗?如果是这样,该怎么做?

编辑

我想知道是否有任何方法(使用一些技巧或我不知道的类)在虚拟机中同时调用一个方法。我想这是不可能的。

4

3 回答 3

1

Thread.sleep您应该通过在方法中间睡觉( )或进行耗时的忙碌工作来减慢方法的处理速度,然后让两个或更多其他线程尽可能快地调用该方法。

您还可以抽象出只运行一次的功能,以便单独测试它。例如

def onlyOnce[A](f: => A) = {
  if (myMethodCalled.getAndSet(true)) throw new Exception("Twice!")
  f
}

然后当你需要测试这是否真的有效时,你传入一个慢慢执行f以使测试变得容易。否则,在您的一次性方法中,您

def doSomething = onlyOnce {
}

如果您已onlyOnce正确测试,则不会出错(假设事物已正确封装,因此主体f不会弄乱 的值myMethodCalled)。

最后,您最好的选择是使用至少具有三个实际执行线程的机器,并让其中两个执行忙等待,其中一个翻转另一个正在读取的 volatile var,然后都运行该方法。这本质上并不可靠,但是如果您在两者之间有小的忙等待偏移量并且多次覆盖相关空间,您至少可以提出一个统计论据,即您至少几乎一直都没事。

于 2013-03-25T22:39:16.153 回答
0

只需将您的 def 更改为惰性 val,您就可以确信它只会运行一次:

object MyObject {

// static field
val myMethodCalled = new AtomicBoolean()   

// static method
lazy val myMethod = {
  if (myMethodCalled.getAndSet(true))
    throw new IllegalStateException("Do not call myMethod twice")
  }
}
于 2013-03-26T00:54:05.103 回答
0

我对 AtomicBoolean 的需求感到有些困惑。因为你正在使用它,所以你应该做体面的事情并编写一个测试。那挺好的。但是,在 JVM 上测试线程代码非常困难(即使没有 JVM 的障碍,在其他语言中也不是特别容易)。

幸运的是,您的情况可能有一个更简单的解决方案。看来您可能正在尝试检测何时意外同时使用了特定方法。你能阻止它被如此使用吗?例如:

class MyObject {
  def myMethod() {
    synchronized {
      .. stuff in here is serialized by the Hoare Monitor
    }
  }
}

一种有效的替代策略是在专门设计的模块中隔离顺序行为。这是 actor 模式背后的一般原则,也是更一般的 CSP 代数(用于 Occam、Go、Limbo 并通过 JCSP API 在 JVM 上可用)。测试顺序代码通常要容易得多,因此这些模式可以帮助您将任务划分为可管理的块。

有四种并发故障,单纯靠测试是无法消除的,前段时间写过一篇文章

于 2013-03-26T21:06:16.413 回答