同步 vs 信号量

28

在阅读Java并发时,我有以下疑问:

  1. Java是否提供了比synchronized更低级别的同步构造?

  2. 在什么情况下我们会使用信号量(semaphore)替代synchronized(它在Java中提供监视器行为)?


我认为对于问题1,我们可以使用ReentrantLock和Condition对象,它们是一些较低级别的构造。 - Addict
3个回答

54

同步机制(Synchronized)只允许一个执行线程同时访问资源。而信号量(Semaphore)则允许最多n个(n可以自行选择)执行线程同时访问资源。


12
  1. 根据http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html中的说明,volatile关键字用于访问变量时比通过同步代码访问这些变量更有效率。

  2. java.util.concurrent.Semaphore用于限制可以访问资源的线程数量。也就是说,当synchronized仅允许一个线程获取锁并执行同步块/方法时,Semaphore允许最多n个线程获得许可并阻塞其他线程。


2
synchronized 提供了解决线程干扰和内存一致性错误的方案,然而 volatile 只提供了解决内存一致性错误的方案,因此我们不能使用 volatile 来提供操作的原子性。我在这里漏掉了什么吗? - Addict
volatile 也提供了对 long/double 的原子访问。 - Evgeniy Dorofeev
使用volatile关键字仍然可能出现脏读并破坏共享变量,因此它不是synchronized的替代品。 - user1954363

3

另外还有原子性操作。这提供了访问基本硬件比较和交换命令的方式,这是所有同步的基础。例如,它允许您安全地增加一个数字。如果您对volatile字段执行++操作,则执行相同指令的另一个线程可能会在您的线程写入该字段之前读取该字段,然后在您的线程之后将其写回。因此,其中一个增量会丢失。 原子操作在“原子”地进行读写,因此避免了这个问题。

实际上,volatile,同步语句和原子操作通常会强制刷新所有线程数据并/或根据需要写入主内存,因此它们都不是真正的低级别操作。(我在这里进行了简化。与C#不同,Java实际上没有“主内存”的概念。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接