首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在静态变量中使用同步

问在静态变量中使用同步
EN

Stack Overflow用户
提问于 2012-07-24 10:35:16
回答 3查看 10.2K关注 0票数 1

我有一个静态地图

代码语言:javascript
复制
private static Map<String, Car> cars = new HashMap<~>() //Map holding car objects

我在如下所示的方法中使用变量

代码语言:javascript
复制
private static String getCar(String name){
    return cars.get(name);
}

所以,如果我想在汽车上加锁,为了线程安全,可以像下面这样做吗?

代码语言:javascript
复制
private static void xyz() {
    synchronized(cars) {
        Car c = getCar("abc");
        c.setColor("Green");
    }
}

有什么建议吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-07-24 10:55:36

Java的synchronized关键字可以应用于任何对象,以便在继续操作之前“获取该对象的锁”(或“同步”该对象)。如果任何其他进程试图同时在同一对象上运行同步的代码,它将一直阻塞,直到锁定该对象的进程退出已同步块。

您同步的对象不必在synchronized块的任何部分实际使用;它可以是一个简单的互斥对象,其唯一目的是在同步块中锁定和解锁。但是,重要的是要注意,简单地在对象上同步并不能防止其他线程修改它,如果它们也没有在该对象上同步的话。它是程序员/约定强制的锁,而不是内置的锁,所有使用共享对象的代码必须“同意”在它上进行同步。

例如,使用上面编写的代码,即使您的xyz()方法在cars上同步,您也可以编写如下所示的另一个方法:

代码语言:javascript
复制
public void changeCar() {
    Car myCar = cars.get("abc");
    myCar.setColor("Blue");
}

在不调用synchronized的情况下修改cars。此方法可以在您的方法xyz()修改"abc“car的同时修改它(即违反线程安全性),因为它不包含在cars上调用synchronized的任何代码。

如果您想确保您的cars映射是线程安全的(即决不会被两个方法同时修改),您必须

get

  • 确保任何修改cars的代码首先调用一个ConcurrentHashMap,这保证了它上的put和get操作是可执行的
票数 4
EN

Stack Overflow用户

发布于 2012-07-24 11:05:28

这很好,但是请注意,使用您当前的代码,您并没有完全锁定cars对象,您仍然可以在其他方法中访问cars并设置属性,除非您在cars对象上再次同步。

代码语言:javascript
复制
public static void otherMethod() {
  synchronized(cars) {
     Car myCar = cars.get("abc");
     myCar.setColor("Red");
  }
}

但是如果xyz()方法是您设置属性的唯一位置,那么您的代码就是线程安全的。

票数 1
EN

Stack Overflow用户

发布于 2012-07-24 11:48:54

如果您只关心单个方法的同步,请使用

代码语言:javascript
复制
Map<String, Car> synchronizedMap = Collections.synchronizedMap(map);

这将自动为映射中的所有方法添加同步,并使每个方法调用成为原子方法。这是您可能应该向线程公开的映射。

但是,如果您需要跨多个方法调用进行同步(如果某个内容为null,则get后面跟着一个put ),则需要使用上面的方法。

注意,Car对象也需要是threadsafe的,如果没有看到这个方法,我就不能说它是还是不是。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11623326

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档