我有一个静态地图
private static Map<String, Car> cars = new HashMap<~>() //Map holding car objects我在如下所示的方法中使用变量
private static String getCar(String name){
return cars.get(name);
}所以,如果我想在汽车上加锁,为了线程安全,可以像下面这样做吗?
private static void xyz() {
synchronized(cars) {
Car c = getCar("abc");
c.setColor("Green");
}
}有什么建议吗?
发布于 2012-07-24 10:55:36
Java的synchronized关键字可以应用于任何对象,以便在继续操作之前“获取该对象的锁”(或“同步”该对象)。如果任何其他进程试图同时在同一对象上运行同步的代码,它将一直阻塞,直到锁定该对象的进程退出已同步块。
您同步的对象不必在synchronized块的任何部分实际使用;它可以是一个简单的互斥对象,其唯一目的是在同步块中锁定和解锁。但是,重要的是要注意,简单地在对象上同步并不能防止其他线程修改它,如果它们也没有在该对象上同步的话。它是程序员/约定强制的锁,而不是内置的锁,所有使用共享对象的代码必须“同意”在它上进行同步。
例如,使用上面编写的代码,即使您的xyz()方法在cars上同步,您也可以编写如下所示的另一个方法:
public void changeCar() {
Car myCar = cars.get("abc");
myCar.setColor("Blue");
}在不调用synchronized的情况下修改cars。此方法可以在您的方法xyz()修改"abc“car的同时修改它(即违反线程安全性),因为它不包含在cars上调用synchronized的任何代码。
如果您想确保您的cars映射是线程安全的(即决不会被两个方法同时修改),您必须
get
cars的代码首先调用一个ConcurrentHashMap,这保证了它上的put和get操作是可执行的发布于 2012-07-24 11:05:28
这很好,但是请注意,使用您当前的代码,您并没有完全锁定cars对象,您仍然可以在其他方法中访问cars并设置属性,除非您在cars对象上再次同步。
public static void otherMethod() {
synchronized(cars) {
Car myCar = cars.get("abc");
myCar.setColor("Red");
}
}但是如果xyz()方法是您设置属性的唯一位置,那么您的代码就是线程安全的。
发布于 2012-07-24 11:48:54
如果您只关心单个方法的同步,请使用
Map<String, Car> synchronizedMap = Collections.synchronizedMap(map);这将自动为映射中的所有方法添加同步,并使每个方法调用成为原子方法。这是您可能应该向线程公开的映射。
但是,如果您需要跨多个方法调用进行同步(如果某个内容为null,则get后面跟着一个put ),则需要使用上面的方法。
注意,Car对象也需要是threadsafe的,如果没有看到这个方法,我就不能说它是还是不是。
https://stackoverflow.com/questions/11623326
复制相似问题