使用可变变量和信号量 - Java
Using volatile variables and semaphores - Java
我从线程、信号量、易失性变量等开始。
我想知道当我使用 Semaphores 时是否有必要将变量定义为 volatile,我的意思是:
有 2 个线程,一个增加变量,另一个减少变量,显然,在每次访问之前,我有一个互斥体,它随时控制只有一个线程 "playing" 与变量。
是否需要定义为volatile?
I wonder if when I'm using Semaphores it is necessary to define the
variable as volatile,
我认为没有这样的限制。互斥量是一种互斥信号量,是信号量的一种特殊变体,一次只允许一个储物柜。它相当于一个计数为1的普通计数信号量,并且要求它只能由锁定它的同一个线程释放。
如果我们在 Java 中专门讨论 信号量:信号量是许可的计数器,获取就像递减,等待而不是低于零。它没有上限。如 CIP 中所述:
The implementation has no actual permit objects, and Semaphore does
not associate dispensed permits with threads, so a permit acquired in
one thread can be released from another thread. You can think of
acquire as consuming a permit and release as creating one; a
Semaphore is not limited to the number of permits it was created with.
对于您的方案,您可以共享一个计数器并使其易变或更好地使用 AtomicInteger
,因为它们使用 CAS
机制,在低竞争下表现非常好。
来自 Semaphore 的 API 文档:
Memory consistency effects: Actions in a thread prior to calling a
"release" method such as release()
happen-before actions following a
successful "acquire" method such as acquire()
in another thread.
因此 read/write 由信号量保护的变量是安全的。无需将它们声明为 volatile
.
信号量不应该用来代替synchronized,因为信号量不持有独占互锁,即使它被初始化为一个,就像一些对象上的synchronized。的确,信号量初始化为一个,一次只允许一个线程访问持有许可的对象。但是持有许可的线程并不拥有它,任何其他线程都可以释放该许可并获得许可。因此,两个线程可以同时访问同一个对象,如果两个线程都操作该对象,则会出现多线程问题,如丢失更新、过时读取等。
在你有 2 个线程的例子中,一个增加一个减少同一个变量。互斥就足够了,不需要 volatile 声明。这里我假设互斥是通过同步而不是信号量实现的。
volatile 不如 synchronized 严格,当执行的操作是原子的(读取或写入) 时,您可能希望使用 volatile。执行 read-update-write 操作时不应使用 volatile。
我从线程、信号量、易失性变量等开始。 我想知道当我使用 Semaphores 时是否有必要将变量定义为 volatile,我的意思是:
有 2 个线程,一个增加变量,另一个减少变量,显然,在每次访问之前,我有一个互斥体,它随时控制只有一个线程 "playing" 与变量。
是否需要定义为volatile?
I wonder if when I'm using Semaphores it is necessary to define the variable as volatile,
我认为没有这样的限制。互斥量是一种互斥信号量,是信号量的一种特殊变体,一次只允许一个储物柜。它相当于一个计数为1的普通计数信号量,并且要求它只能由锁定它的同一个线程释放。
如果我们在 Java 中专门讨论 信号量:信号量是许可的计数器,获取就像递减,等待而不是低于零。它没有上限。如 CIP 中所述:
The implementation has no actual permit objects, and Semaphore does not associate dispensed permits with threads, so a permit acquired in one thread can be released from another thread. You can think of acquire as consuming a permit and release as creating one; a Semaphore is not limited to the number of permits it was created with.
对于您的方案,您可以共享一个计数器并使其易变或更好地使用 AtomicInteger
,因为它们使用 CAS
机制,在低竞争下表现非常好。
来自 Semaphore 的 API 文档:
Memory consistency effects: Actions in a thread prior to calling a "release" method such as
release()
happen-before actions following a successful "acquire" method such asacquire()
in another thread.
因此 read/write 由信号量保护的变量是安全的。无需将它们声明为 volatile
.
信号量不应该用来代替synchronized,因为信号量不持有独占互锁,即使它被初始化为一个,就像一些对象上的synchronized。的确,信号量初始化为一个,一次只允许一个线程访问持有许可的对象。但是持有许可的线程并不拥有它,任何其他线程都可以释放该许可并获得许可。因此,两个线程可以同时访问同一个对象,如果两个线程都操作该对象,则会出现多线程问题,如丢失更新、过时读取等。
在你有 2 个线程的例子中,一个增加一个减少同一个变量。互斥就足够了,不需要 volatile 声明。这里我假设互斥是通过同步而不是信号量实现的。
volatile 不如 synchronized 严格,当执行的操作是原子的(读取或写入) 时,您可能希望使用 volatile。执行 read-update-write 操作时不应使用 volatile。