Java 多线程访问的单例类中的实例变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18944184/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Instance variable in a Singleton class accessed by multiple threads
提问by Mellon
I have a singleton class:
我有一个单例类:
public class School {
private HashMap<String, String> students;
private static School school;
private School(){
students = new HashMap<String, String>();
}
public static School getInstance(){
if(school == null){
school = new School();
}
return school;
}
//Method to add student
protected void addStudent(String id, String name){
students.put(id,name);
}
//Method to remove student
protected void removeStudent(String id){
students.remove(id);
}
}
As you can see above, in the singleton class, I have a students
variable (a HashMap
), there are methods to add & remove student in the class.
正如你在上面看到的,在单例类中,我有一个students
变量 (a HashMap
),有在类中添加和删除学生的方法。
In my application, there could be multiple threads using this School
class to getInstance()
, then adding & removing student. To make the access (especially the access tostudents
instance) be thread safe, I am thinking to use synchorized
keyword for getInstanc()
method, like:
在我的应用程序中,可能有多个线程使用这个School
类getInstance()
,然后添加和删除学生。为了使访问(尤其是对students
实例的访问)成为线程安全的,我想synchorized
为getInstanc()
方法使用关键字,例如:
public synchronized static School getInstance(){
if(school == null){
school = new School();
}
return school;
}
But I think my trivial change only can make sure only oneSchool
instance be created in multi-thread environment. What else do I need to do in order to make it thread safe for accessing thestudents
instance by multiple threads as well. Any good suggestion or comment is appreicated, thanks!
但我认为我的微不足道的更改只能确保在多线程环境中只创建一个School
实例。我还需要做什么才能使多个线程访问students
实例的线程安全。任何好的建议或意见都值得赞赏,谢谢!
采纳答案by dasblinkenlight
Leaving the conversation on whether singletons are evil or not, let's consider only the thread safety issues in your School
class:
离开关于单身人士是否邪恶的话题,让我们只考虑School
班级中的线程安全问题:
- The shared object is created "lazily"- this needs synchronization to avoid making two instances of
School
; you have correctly identified and fixed this issue. However, since initializingSchool
does not take much time, you might as well makegetInstance()
a trivial getter by initializingschool = new School()
eagerly. - The hash map inside the School- concurrent access to the hash map will result in exceptions. You need to add synchronization around the code that adds, removes, and iterates students to avoid these exceptions.
- Access to individual students- once the callers get a
Student
object, they may start modifying it concurrently. Therefore theStudent
object needs concurrency protection of their own.
- 共享对象是“懒惰地”创建的- 这需要同步以避免创建两个实例
School
;您已正确识别并修复了此问题。但是,由于初始化School
不需要太多时间,您不妨getInstance()
通过school = new School()
急切地初始化来制作一个简单的 getter 。 - School 内部的哈希映射——并发访问哈希映射会导致异常。您需要在添加、删除和迭代学生的代码周围添加同步以避免这些异常。
- 访问个别学生- 一旦调用者获得一个
Student
对象,他们就可以同时开始修改它。因此Student
对象需要自己的并发保护。
回答by Joni
The HashMap implementation is not thread-safe, so bad things may happen if several thread operate on it at the same time. A quick fix is making the map itself synchronized:
HashMap 实现不是线程安全的,因此如果多个线程同时对其进行操作,可能会发生不好的事情。快速修复是使地图本身同步:
students = Collections.synchronizedMap(new HashMap<String, String>());
Note that if you iterate on this map, the iteration also has to be made in a synchronized
block; otherwise other threads may modify the map while you are iterating.
请注意,如果您在此地图上进行迭代,则迭代也必须在synchronized
块中进行;否则其他线程可能会在您迭代时修改地图。
A thread-safe alternative to HashMap
is ConcurrentHashMap
线程安全的替代方案HashMap
是ConcurrentHashMap
回答by Vikas
Synchronizing method makes them thread safe it means only one thread can execute that method at a time.
同步方法使它们成为线程安全的,这意味着一次只有一个线程可以执行该方法。
However, in above situation, i would suggest to synchronized addStudent and removeStudent method only. Or you can synchronized students hash map also using -
但是,在上述情况下,我建议仅同步 addStudent 和 removeStudent 方法。或者你也可以使用同步学生哈希映射 -
Collections.synchronizedMap(new HashMap());
Collections.synchronizedMap(new HashMap());
回答by Srikanth Reddy Lingala
You can use a ConcurrentHashMapor a Collections.synchronizedMap
您可以使用ConcurrentHashMap或Collections.synchronizedMap
Thisarticle gives a good explanation
这篇文章给出了很好的解释