2014-03-31 62 views
0

我想同步通过ExecutorService调用的3个线程。我如何确保它们在同一个对象上同步?这些线程同步的对象

现在我有这样的代码:

class Test { 
    executor.submit(new Request(threadNames[i])); 
    executor.submit(new Request(threadNames[i])); 
    executor.submit(new Request(threadNames[i])); 

    private class Request implements Callable { 
     @Override 
     public Long call() throws InterruptedException { 
      if (threadName.equals("SOMETHING") { 
       doSomething(); 
      } else { 
       doSomeOtherThing(); 
      } 
     } 
    } 

    private synchronized void doSomething() { 
    } 

    private synchronized void doSomeOtherThing() { 
    } 

    ... 
} 

其中一个线程负责生成条件和其他2行为就可以了。

+0

用于同步'doSomething'和'doSomeOtherThing'的锁将在创建'Request'的'Test'的实例中。很难确切地说出发生了什么,因为你的代码是不完整的,并且不能以其当前形式工作 - 执行程序调用在“测试”类 –

回答

1
  1. 你没有得到提交线程执行人服务;您提交任务,稍后将在Executor线程池中的某个线程上执行该任务;

  2. 如果一个任务是生产者而另外两个是消费者,那么将所有三个任务提交给执行者是错误的。它很容易导致死锁,消费者任务无限期地等待生产者,但生产者无法运行,因为消费者占用了所有线程。

反思您的解决方案,以便生产者任务也负责提交消费者任务给执行者;任务可以用产生的值来实例化,所以协调问题一开始就解决了。

+0

中显示的位置是没有意义的我知道我们提交任务执行者 - 服务。这是我的问题陈述: 我想生成由2个测试线程调用的所有可能的API调用交叉。为了实现这一点,我想为每个请求分配一个线程,其中一个请求由多个API调用组成。我希望线程在调用每个方法后暂停,并且我想要另一个线程,例如调度程序发信号通知/决定哪个测试线程应该基于简单的置换进行。 – user1071840

+0

我目前正在同步同步方法和wait()和notify()所有3个线程都提交给执行器服务,我显然正在运行到死锁。 – user1071840

+0

您意识到trickies并发问题不是源于交错,而是来自写入可见性问题?如果您只是想测试API调用的交错,那么使用任何这种交错的简单顺序执行就足够了。否则,为了真正测试线程的安全性,任何类型的同步都是不可能的,因为它引入了通常不存在的* happen-before *关系,掩盖了数据竞争问题。 –

0

作为每文档(http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html):

每个对象具有与之相关联的本征锁。按照惯例, 需要对对象的 字段进行独占且一致访问的线程必须在访问 之前获取对象的内部锁定,然后在内部锁定完成时释放内部锁定。 A 线程据说拥有内部锁定,它具有获取锁定并释放锁定的时间。

当线程调用同步方法时,它会自动获取 该方法对象的内部锁,并在 方法返回时释放它。即使返回由未捕获的异常导致 ,也会发生锁定释放。

您可能想知道在调用静态同步方法 时会发生什么,因为静态方法与类关联,而不是与 对象关联。在这种情况下,线程获取与该类关联的 Class对象的内部锁。因此,对类的静态 字段的访问由与该类的任何 实例的锁不同的锁控制。

所以,你的方法是从Test对象usning内部锁,是的,因为马尔科已经正确地指出,你可能会得到一个僵局。