繁体   English   中英

当少数线程尝试调用相同的同步方法时会发生什么?

[英]What happens when few threads trying to call the same synchronized method?

所以我参加了这场赛马,当一匹马到达终点线时,我调用了到达方法。 假设我有10个线程,每匹马一个,而第一个到达的马确实调用了“到达”:

public class FinishingLine {
    List arrivals;
    public FinishingLine() {
        arrivals = new ArrayList<Horse>();
    }

    public synchronized void arrive(Horse hourse) {
        arrivals.add(hourse);
    }
}

我将Ofc方法设置为“同步”,但我不完全了解如果不同步会发生什么,这位教授只是说这并不安全。

我想更好地理解的另一件事是,如何确定第一个线程完成后将使用哪个线程? 第一个线程完成“到达”并且方法解锁后,下一个线程将运行?

1)行为将是不确定的,但是您应该假定它不是您希望它以任何可以依赖的方式进行的行为。

如果两个线程尝试同时添加,则可能同时添加了两个元素(以任一顺序),仅添加了一个元素,或者甚至都没有添加。

Javadoc的相关引用是:

请注意,此实现未同步 如果多个线程同时访问ArrayList实例,并且至少有一个线程在结构上修改列表,则必须在外部进行同步。 (结构修改是添加或删除一个或多个元素或显式调整后备数组大小的任何操作;仅设置元素的值不是结构修改。)

2)这取决于操作系统如何调度线程。 对于常规同步块,不能保证“公平”(按到达顺序执行),尽管有某些类( 信号量是一种)可以选择公平执行顺序。

例如,您可以使用信号量实施公平的执行命令:

public class FinishingLine {
    List arrivals;
    final Semaphore semaphore = new Semaphore(1, true);

    public FinishingLine() {
        arrivals = new ArrayList<Horse>();
    }

    public void arrive(Horse hourse) {
        semaphore.acquire();
        try {
          arrivals.add(hourse);
        } finally {
          semaphore.release();
        }
    }
}

但是,使用公平的阻塞队列来完成此操作会更容易,该队列为您处理并发访问:

public class FinishingLine {
  final BlockingQueue queue = new ArrayBlockingQueue(NUM_HORSES, true);

  public void arrive(Horse hourse) {
    queue.add(hourse);
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM