【问题标题】:Locking threads in java doesnt work在java中锁定线程不起作用
【发布时间】:2014-07-11 15:30:15
【问题描述】:

我对多线程有一个简单的问题,我只是想不通。我尝试了同步方法和使用锁,但这些都不起作用,所以我希望这里有人可以帮助我。

public void startThreads(ArrayList<ArrayList<Tocka>> pLista) {
        ScheduledThreadPoolExecutor eventPool = new ScheduledThreadPoolExecutor(pLista.size());
            for(int i=0; i<pLista.size(); i++) {
                eventPool.execute(new Dretva(pLista.get(i),i));
            }
    }

public synchronized void run() {
        lock.lock();
        System.out.print(this.id + ". ");
        optimalnost.printOrder(this.lista);
        double distance = optimalnost.getDistanceList(this.lista);
        System.out.println(" - " + distance);
        System.out.println();
        checkMin(distance);
        lock.unlock();
    }

我使用列表列表从测试类 startThreads 方法调用(startThreads 和线程在单独的类中)。在 Dretva 类(线程)中,我有一个运行代码,它使用作为参数传递的列表执行一些计算并打印计算。在我的示例中,有 6 个列表,我试图通过所有列表,但当时只有一个。当我不使用线程时它可以正常工作,但是使用这样的线程我会搞砸并打乱输出。

我需要帮助如何在活动线程未完成时让其他线程等待。

这是我的问题的截图:

【问题讨论】:

  • 您的同步问题是每个线程都是Dretva 的不同实例。 synchronized 关键字仅锁定对对象的一个​​特定实例上的方法的访问。我不知道您对锁的问题是什么,因为我看不到您在哪里声明了锁。我的猜测是你给Drevta 的每个实例都提供了自己的锁。你能扩展一下吗?
  • 感谢您的快速回答。我所做的只是在 Dretva 类中声明锁,如下所示: ReentrantLock lock = new ReentrantLock();它在 Dretva 的所有方法之外,就在类中。
  • 是的,那是你的问题。锁必须在所有线程中都是全局的。否则,您将为每个班级锁定。请参阅下面的 Tim B 的答案。他用代码很好地解释了它。
  • 是的,通过这样声明,每个实例都有一份副本
  • 这就是问题所在,谢谢大家的帮助:D

标签: java multithreading synchronization locks


【解决方案1】:

同步方法在该对象上同步,而不是全局同步。

只需传入一个对象并对其进行同步:

public void startThreads(ArrayList<ArrayList<Tocka>> pLista) {
    final Object lockOb = new Object();

    ScheduledThreadPoolExecutor eventPool = new ScheduledThreadPoolExecutor(pLista.size());
        for(int i=0; i<pLista.size(); i++) {
            eventPool.execute(new Dretva(lockOb, pLista.get(i),i));
        }
}

Object lockOb;

public void run() {
    synchronized(lockOb) {
       System.out.print(this.id + ". ");
       optimalnost.printOrder(this.lista);
       double distance = optimalnost.getDistanceList(this.lista);
       System.out.println(" - " + distance);
       System.out.println();
       checkMin(distance);
    }
}       

现在所有的对象都共享一个锁对象并且都在这个对象上同步,所以一次只会运行一个。这确实完全违背了使用线程的意义,因为您已经创建了许多线程,然后故意让它一次只能执行其中一个线程。

作为旁注,对于任何需要解锁的锁定对象,您应该始终使用 try finally 块。

【讨论】:

  • 蒂姆是正确的。 synchronized 关键字对 run 方法没有任何作用。他还解决了我假设您遇到的问题,即锁不是全局的并且特定于每个线程。
【解决方案2】:

您的同步方法run 是一个成员方法。这意味着您正在对对象的实例进行同步。由于您创建了多个实例,因此每个实例都获得了对不同对象的锁定。如果您希望跨实例同步访问,则必须显式提供互斥锁以锁定或使用静态常量互斥锁让所有实例同步。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 2022-12-06
    • 2014-09-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多