什么是 Java Semaphore 和 Mutex – Java Concurrency MultiThread 举例说明

已发表: 2015-03-12

Crunchify 的 Java Mutex 和信号量教程

Java并发是一个非常广泛的话题。 有数百个教程和示例可供使用。 前段时间我写过一些关于在 Java 中并发运行多个线程和不同类型的同步块的教程。

在本教程中,我们将介绍:

  1. 互斥量的解释
  2. 信号量的解释
  3. 两个有细节的例子

让我们开始吧

在阅读以下说明时Let's keep this in mind

  • 以 Shopper 和 Customer 为例
  • 购物者正在借笔记本电脑
  • 客户可以来使用笔记本电脑——客户需要钥匙才能使用笔记本电脑
  • 使用后 – 客户可以将笔记本电脑退还给购物者

什么是互斥锁(只有 1 个线程):

购物者有笔记本电脑的钥匙。 一位客户当时可以拥有钥匙——借用一台笔记本电脑。 当任务完成时,Shopper 将钥匙交给(释放)队列中的下一位顾客。

Official Definition

“互斥锁通常用于序列化对cannot be executed concurrently的可re-entrant code部分的访问。 互斥对象只允许一个线程进入受控部分,迫使试图访问该部分的其他线程等待,直到第一个线程退出该部分。”

换句话说: Mutex = Mutually Exclusive Semaphore

什么是信号量(N个指定线程):

假设现在 Shopper 有 3 台相同的笔记本电脑和 3 个相同的钥匙。 信号量是free identical Laptop keys的数量。 信号量计数——键的数量——在开始时设置为 3(所有三台笔记本电脑都是空闲的),然后随着客户进来,计数值递减。如果所有笔记本电脑都在使用,即没有空闲键可供使用笔记本电脑,信号量计数为 0。现在,当任何客户返回笔记本电脑时,信号量增加到 1(一个空闲密钥),并提供给队列中的下一个客户。

Official Definition :“信号量将共享资源的同时用户数限制为最大数量。 线程可以请求对资源的访问(减少信号量),并且可以发出信号表明它们已经完成了对资源的使用(增加信号量)。”

另一个必须阅读:单例线程安全实例的延迟创建

示例 1:(解释如下)

在上面的教程CrunchifySemaphoreMutexTutorial.java ,当CrunchifyProducerthreadName添加到crunchifyList linkedList 对象时,它可以向信号量发出信号。

然后, CrunchifyConsumer可以尝试获取信号量,因此它们将一直等待,直到 CrunchifyProducer 发出已添加线程 ID 的信号。 在发出添加数据的信号后,其中一个消费者将被唤醒,它会知道它可以读取一个 crunchifyList 对象。 它可以读取一个列表,然后返回尝试获取信号量。

如果在那个时候,生产者已经写了另一个数据包,它会再次发出信号,然后任何一个消费者将继续读取另一个数据包,依此类推……

换一种说法:

结果:

如何防止竞态条件:

What if you have multiple Consumers? 在上面的 Java 教程中,消费者(不是生产者)在读取数据包时(而不是在获取信号量时)应该锁定缓冲区,以防止竞争条件。 在下面的示例中,生产者还锁定了列表,因为所有内容都在同一个 JVM 上。

示例 2:

结果: