java - 当几个线程尝试调用同一个同步方法时会发生什么?

标签 java multithreading synchronized

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

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

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

Ofc我将到达方法设置为同步,但我不完全理解如果不同步会发生什么,教授只是说这不安全。

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

最佳答案

1) 行为是什么是未定义的,但您应该假设它不是您希望它以您可以依赖的任何方式执行的操作。

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

相关引用来自Javadoc是:

Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification.)

2) 这取决于操作系统如何调度线程。尽管有某些类( Semaphore 就是其中之一)可以让您选择公平的执行顺序,但常规同步块(synchronized block)无法保证“公平”(按到达顺序执行)。

例如您可以使用信号量实现公平的执行顺序:

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();
        }
    }
}

但是,使用 fair blocking queue 会更容易做到这一点,它为您处理并发访问:

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

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

关于java - 当几个线程尝试调用同一个同步方法时会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34104416/

相关文章:

java - 如何制作AWT Button()并使用ImageIcon()、Icon()?

java - 将项目从eclipse导入到android studio( Unresolved 资源)

java - 新列表<A & ?扩展 B>();

java - 如何测试 AtomicBoolean 的原子性?

java - 如何在 Java 中使用 ThreadPoolExecutor 处理 RejectedExecutionException

java - 根据 java 内存模型,synchronized 到底做了什么?

java - 如何调整 smartgwt 的 Listgrid 的行号列?

C#.NET 4.0 并发字典 : TryRemove within a lock?

java - Java 中的同步列表/映射(如果只有一个线程正在写入)

java - 在 Java 中跟踪 websocket 连接的最佳实践