【问题标题】:Which object do these threads synchronize on这些线程在哪个对象上同步
【发布时间】:2014-03-31 11:02:34
【问题描述】:

我想同步通过 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() {
    }

    ...
}

其中一个线程负责生成一个条件,而另外两个则对其进行操作。

【问题讨论】:

  • 用于同步doSomethingdoSomeOtherThing 的锁将在Test 的实例上创建Request。很难准确判断发生了什么,因为您的代码不完整,并且无法以当前形式运行 - executor 调用在 Test 类中的显示位置没有意义

标签: java multithreading monitor synchronized


【解决方案1】:
  1. 您无法向 Executor 服务提交 线程;您提交 tasks,稍后将在 Executor 线程池中的一个线程上执行;

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

重新考虑你的解决方案,让生产者任务也负责将消费者任务提交给执行者;任务可以用产生的值来实例化,所以协调问题一开始就解决了。

【讨论】:

  • 我了解到我们将任务提交给 executor-service。这是我的问题陈述:我想生成由 2 个测试线程调用的 API 调用的所有可能交错。为了实现这一点,我想为每个请求分配一个线程,其中一个请求由许多 API 调用组成。我希望线程在调用每个方法后暂停,我想要另一个线程,比如调度程序信号/决定哪个测试线程应该基于简单的排列继续。
  • 我目前正在与同步方法和 wait() 和 notify() 同步,其中所有 3 个线程都提交给执行程序服务,显然陷入了死锁。
  • 您确实意识到棘手的并发问题并非源于交错,而是源于写入可见性问题?如果您只想测试 API 调用的交错,那么使用任何此类交错的简单顺序执行就足够了。否则,要真正测试线程安全,任何类型的同步都是不可能的,因为它引入了通常不存在的 happens-before 关系,从而掩盖了数据竞争问题。
【解决方案2】:

根据文档 (http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html):

每个对象都有一个与之关联的内在锁。按照惯例, 需要对对象的独占和一致访问的线程 字段必须在访问之前获取对象的内在锁 它们,然后在完成它们后释放内在锁。一个 据说线程在它拥有的时间之间拥有内在锁 获取锁并释放锁。

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

你可能想知道当一个静态同步方法是 调用,因为静态方法与类相关联,而不是 目的。在这种情况下,线程为 与类关联的类对象。从而访问类的静态 字段由不同于任何锁的锁控制 类的实例。

因此,您的方法使用来自 Test 对象的内在锁,是的,正如 Marko 正确指出的那样,您可能会遇到死锁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-08
    • 2016-10-31
    • 1970-01-01
    • 2015-01-21
    • 1970-01-01
    • 2013-04-02
    • 1970-01-01
    相关资源
    最近更新 更多