3 回答
TA贡献1784条经验 获得超7个赞
基本上,您在这里尝试做的是valueSet用作布尔标志来同步Consumer和Producer-- 使它们依次工作。真的,valueSet只能在一瞬间是真的或假的;然而,这不是两个线程(消费者和生产者)如何看待它。
我们知道在 Java 中,对象存储在堆上;那就是所谓的主存。但是,对于每个线程,出于性能考虑,对所用对象的引用都保存在特定于线程的缓存中。如在这里,Producer和Consumer共享一个Item被存储在堆上对象; 该字段item.valueSet可能被每个线程缓存。
_______________ ______________
| Consumer | | Producer |
| _________ | | _________ |
| | | | | | | |
| | Cache1 | | | | Cache2 | |
| | valueSet| | | | valueSet| |
| |_________| | | |_________| |
|_______________| |______________|
| | | |
| | | |
_|_|______________|_|__
| |
| MAIN MEMORY |
| valueSet |
|_______________________|
例如,当Consumer更改valueSet为 时false,它可能会也可能不会将新值刷新到主内存;类似地,当Producer检查时valueSet,它可能会也可能不会尝试从主内存中读取最新值。这就是volatile关键字发挥作用的地方。当您设置valueSet为 时volatile,它确保两个线程向/从主内存写入/读取最新值。
请注意,上面的总结基本上被称为JVM 内存模型。它是一组规则,用于定义多线程情况下 JVM 的行为。
如果您尝试更改代码的以下部分:
**volatile** boolean valueSet = false ;
**volatile** int item = 0 ;
...
item.produce((int)(Math.random()*100)) ; // added parenthesis
您将看到以下输出:
Started producer and consumer threads :
Consuming !
Producing ....
Produced : 83
Producing ....
Consumed : 83
Consuming !
Produced : 54
Producing ....
Consumed : 54
Consuming !
Produced : 9
Producing ....
Consumed : 9
Consuming !
Produced : 23
Producing ....
Consumed : 23
TA贡献2037条经验 获得超6个赞
首先,您需要创建共享变量volatile
。
允许线程将其局部变量放在寄存器中,所以是的,一个线程可以将其valueSet
视为 false,而另一个线程可以将其视为true
. 同时。使变量volatile
强制每次都从内存中读取。
但是,这并不能保证代码没有其他问题。同步可能很棘手。但是研究volatile
以克服最可能的原因。
添加回答
举报