我从Threads,Semaphores,volatile变量等开始。 我想知道当我使用信号量时,有必要将变量定义为volatile,我的意思是:
有2个线程,一个增加,另一个减少变量,例如,显然,在每次访问之前,我有一个互斥量,任何时候控制只有一个线程“正在”变量。
有必要定义为volatile?
答案 0 :(得分:3)
来自Semaphore的API文档:
内存一致性效果:调用之前线程中的操作 "释放"诸如
release()
之类的方法发生在之后的行动中 成功"获得"另一个帖子中的acquire()
等方法。
因此,读取/写入由信号量保护的变量是安全的。
答案 1 :(得分:2)
信号量不应该在synchronized的位置使用,因为即使将信号量初始化为1,信号量也不会保持独占的互锁,就像在某个对象上同步一样。确实,信号量初始化为1,一次只允许一个线程访问持有许可证的对象。但持有许可的线程不拥有它,任何其他线程都可以释放该许可并获得许可。因此,两个线程可以同时访问同一个对象,如果两个线程都操纵该对象,则会出现多线程问题,如丢失更新,过时读取等。
在你有两个线程的例子中,一个增加,一个减少同一个变量。相互排斥是充分的,不需要挥发性声明。在这里,我假设互斥是通过同步而不是通过信号量实现的。
volatile不比synchronized更严格,当执行的操作是原子(读或写)时,您可能希望使用volatile。执行读取 - 更新 - 写入操作时不应使用volatile。
答案 2 :(得分:1)
我想知道当我使用信号量时,有必要定义 变量为volatile,
我认为没有任何此类限制。互斥量是互斥信号量,是信号量的特殊变体,一次只允许一个锁定器。它相当于一个计数为1的正常计数信号量,并且要求它只能被锁定它的同一个线程释放。
如果我们专门针对Java中的Semaphore谈论 :信号量是许可证的计数器,并且获取就像是等待而不是低于零的递减。它没有上限。如CIP中所述:
实现没有实际的许可对象,而Semaphore也没有 没有将分发的许可证与线程相关联,因此获得许可证 一个线程可以从另一个线程释放。你可以想到 以消费许可和获得许可获得;一个 信号量不仅限于创建它的许可数量。
对于您的方案,您可以共享计数器并使其变得易变或更好地使用AtomicInteger
,因为它们使用CAS
机制,在低争用下表现非常好。