Java 同步类级别以上的调用
这是一个设计问题,我试图找出应该在哪个级别(应用程序、类、对象或更精细的级别)放置锁以确保原子性 我有一个应用程序,比如说Java 同步类级别以上的调用,java,multithreading,concurrency,locking,Java,Multithreading,Concurrency,Locking,这是一个设计问题,我试图找出应该在哪个级别(应用程序、类、对象或更精细的级别)放置锁以确保原子性 我有一个应用程序,比如说Engine,它有一个class a,还有一个包含map的方法 class A{ public void methodA(){ Map<X,Y> testMap = Maps.newHashMap(); } } 我应该提到的是,我正在考虑第四个选项,因为应用程序引擎可以有多个实例。 现在,当多个线程试图读取和写入映射时,我面临着竞争
Engine
,它有一个class a
,还有一个包含map的方法
class A{
public void methodA(){
Map<X,Y> testMap = Maps.newHashMap();
}
}
我应该提到的是,我正在考虑第四个选项,因为应用程序引擎可以有多个实例。
现在,当多个线程试图读取和写入映射时,我面临着竞争条件
对于选项1,我得到了bucket level lock,因为不同的线程可以指向引擎的不同实例
对于选项2,我得到的对象级别锁与选项1面临相同的问题
对于选项3,我得到了类级锁,它与多实例应用程序有着相同的缺陷
选择4似乎是最可行的选择。但是,它会带来性能开销。因此,Java中是否有某种方法可以确保在类级别锁定,并且不允许线程修改应用程序的不同实例
编辑
参考Chetan的评论,这个本地映射后来被用来与数据库的dao对话,该数据库是全局的,这就是遇到竞争条件的地方
ConcurrentHashMap
即使在“获取”时所有操作都是线程安全的,但它可能反映也可能不反映“put”
Collections.synchronizedMap
synchronizedMap(映射)创建了一个阻塞映射,这将降低性能,尽管可以确保一致性。仅当每个线程需要地图的最新视图时,才使用此选项
方法外部的静态同步映射a
与3相同
使用Redis或Memcache的应用程序级锁
从你的问题中我了解到,只有这个选项才有意义
这是我对您的需求的理解,如果我错了,请纠正我,并相应地更新答案:-您有多个“引擎”应用程序实例(如多个JVM中的多个实例)。在将映射(每个实例的局部映射)持久化到数据库中时,必须避免竞争条件testMap
是一个局部变量。这里不必担心原子性。你说的多实例是什么意思?@KingJulien顾名思义。我可以给你举一个例子,比如在Hadoop中,它有一个主数据节点实例和相应的从数据节点实例。“这个局部映射后来被用来与数据库的dao对话,它是全局的,这就是遇到竞争条件的地方。”所以,map是一个局部变量,你没有任何竞争条件。。。因此,现在您有了此映射的多个实例,并且正在尝试将其插入/更新到“全局”数据库中。。我的理解正确吗?我不能自信地准确地指出我在哪里遇到了比赛条件,但我非常确定,它不会完全发生在应用程序的多个实例上。即使在使用当前实现运行单个实例时,也会遇到方法争用条件的不同线程调用。可以使用选项3进行补救。但是我需要解决多实例的问题。是的,我基本上想要保持这个映射,使它成为全局的而不是局部的。
1.ConcurrentHashMap
2.Collections.synchronizedMap
3.static synchronizedMap outside the methodA
4.Application level locks using Redis or Memcache