繁体   English   中英

使用 volatile 变量和信号量 - Java

[英]Using volatile variables and semaphores - Java

我从线程、信号量、易失性变量等开始。我想知道当我使用信号量时是否有必要将变量定义为易失性,我的意思是:

有 2 个线程,一个增加,另一个减少变量,例如,很明显,在每次访问之前,我有一个互斥锁,可以随时控制只有一个线程在“玩”变量。

有必要定义为 volatile 吗?

来自Semaphore 的API 文档:

内存一致性影响:在调用“释放”方法(如release()之前线程中的操作发生在另一个线程中成功的“获取”方法(如acquire()之后的操作之前

所以读/写由信号量保护的变量是安全的。 无需将它们声明为volatile

不应该使用信号量代替同步,因为即使初始化为一,信号量也不持有互斥互锁,就像在某个对象上同步一样。 确实,信号量初始化为 1,一次只允许一个线程访问持有许可的对象。 但是持有许可的线程并不拥有它,任何其他线程都可以释放该许可并获得该许可。 因此,两个线程可以同时访问同一个对象,如果两个线程都操作该对象,则会出现多线程问题,例如丢失更新、过时读取等。

在您有 2 个线程的示例中,一个增加一个减少相同的变量。 互斥就足够了,不需要 volatile 声明。 在这里,我假设互斥是通过同步而不是信号量实现的。

volatile 不如 synchronized 严格,当执行的操作是原子(读或写)时,您可能希望使用 volatile 。 执行读-更新-写操作时不应使用 volatile。

我想知道当我使用信号量时是否有必要将变量定义为 volatile,

我不认为有任何这样的限制。 互斥体是一种互斥信号量,是信号量的一种特殊变体,一次只允许一个储物柜。 它相当于一个计数为 1 的普通计数信号量,并且要求它只能由锁定它的同一个线程释放。

如果我们专门讨论Java 中的信号量:信号量是许可的计数器,而获取就像递减,它等待而不是低于零。 它没有上限。 正如 CIP 中提到的:

该实现没有实际的许可对象,并且信号量不会将分配的许可与线程相关联,因此可以从另一个线程释放在一个线程中获得的许可。 您可以将获取视为使用许可,而将发布视为创建许可; 信号量不限于创建它时使用的许可数量。

对于您的场景,您可以共享一个计数器并使其可变或更好地使用AtomicInteger因为它们使用CAS机制,在低争用下表现非常好。

暂无
暂无

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

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