我已阅读Java Concurrency in Practice并留下了这个问题:当我使用ConcurrentHashMap时,我还需要担心本书第一部分中讨论的数据并发问题?以下是我的一个程序中的几个例子:
1。交易者的当前位置(共享整数,其中'整数'是数学术语)
此数字表示trader
对象当前拥有的内容并定义其状态。它必须阅读它的位置以了解该做什么(寻找开始一个新的位置,或管理当前的位置)。 Trader
方法在自己的线程上运行。
broker
对象负责设置trader
的位置。每当交易者的一个订单被填满时,它将设置头寸。 Broker
个方法在自己的线程上运行。
trader
和broker
都在同一个包中。职位以包私有static ConcurrentHashMap
的形式实施。键是交易者对象的id。值为Integer。
包的外部是应用程序。它通过公共吸气剂间接获得交易者的头寸。
每隔几分钟,位置最多会改变一次,因此broker
不会经常触及地图。但是,trader
和应用程序将经常阅读。此外,我们经常有几个交易者同时阅读地图。
因此,以这种方式使用ConcurrentHashMap,我不必处理锁定和数据可见性问题? ConcurrentHashMap可以处理所有事情吗?
2。市场(买入价,卖出价,最后价格)
与位置几乎相同的情况,除了现在broker
将非常频繁地更新价格(在繁忙时间每秒最多10次更新;通常是每秒几次)。 trader
和应用程序仍然会频繁读取。现在,地图键是指示哪个库存或未来的代码,值是保持市场价格的对象。
它似乎工作正常,但在阅读JCIP之后,我意识到如果事情没有正确实现,程序仍然会被破坏。这本书讨论了ConcurrentHashMap,但没有明确告诉我第一部分我们不再需要手动解决的问题。 出现,在这种情况下,我没有synchronize
任何内容。这是对的吗?
答案 0 :(得分:3)
是的,ConcurrentHashMap
负责可见性和锁定,只要:
get/put/putIfAbsent
。答案 1 :(得分:3)
所以这样使用ConcurrentHashMap, 我不需要关于锁定和工作 数据可见性? ConcurrentHashMap 照顾好一切?
这取决于地图中的内容,如果我正确阅读了您的示例,情况就像这样
static final ConcurrentMap<Integer,Integer> map = ...
class Trader{
public int doRead(){
map.get(someId);
}
}
class Broker{
public void doWrite(){
map.put(someId,someValue);
}
}
如果是这种情况,那么是的,所有的并发性都得到了解决。
但是,如果地图看起来像
static final ConcurrentMap<Integer,Trader> map = ..
class Broker{
public void doWrite(){
map.get(someId).setPosition(somePosition);
}
}
这不是线程安全的,即使在放置时ConcurrentHashMap锁定,此时对象的所有并发访问都必须处理它们自己的同步。
答案 2 :(得分:2)
除非你说的是每秒超过100,000次更新/读取,否则我不会考虑使用多个线程。原因是线程安全组件比没有组件的组件花费的时间长许多倍。因此,如果一个组件需要花费5倍的时间来保证线程安全,那么你需要同时使用5个以上的线程来实现收支平衡,更不用说更快了。
当您执行相对昂贵的操作时,多个线程更有用。作为一个线程,更新头寸或价格会更有效率。