Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
你能在Java中锁定一个本地对象吗?_Java_Concurrency - Fatal编程技术网

你能在Java中锁定一个本地对象吗?

你能在Java中锁定一个本地对象吗?,java,concurrency,Java,Concurrency,我有这段代码 private Templates retrieveFromCache(String name) { TemplatesWrapper t = xlCache.get(name); synchronized(t){ if (!t.isValid()) { xlCache.remove(name); return null; }

我有这段代码

private Templates retrieveFromCache(String name) {
        TemplatesWrapper t = xlCache.get(name);
        synchronized(t){
            if (!t.isValid()) {
                xlCache.remove(name);
                return null;
            }
        }
        return t.getTemplate();
    }
xlCache
是一个
ConcurrentHashMap
;我之所以在
t
上同步,是因为当线程1验证谓词线程2已经从映射中删除了对象时,两个线程可能会交错,然后抛出
NullPointerException
我的假设正确吗?因为我知道并发是比较难推理的事情之一。然后是我最初的问题,我能锁定
t
,即使它是本地的吗

这也是从
public
方法调用的
private
方法,它是否会造成差异


EDIT:我最初的前提是抛出
NullPointerException
,这是不正确的,因为
remove()
返回
boolean
使同步变得毫无意义;但是,我的问题是锁定本地对象的问题得到了回答。
ConcurrentHashMap
(通常是
Map
/
ConcurrentMap
)如果指定的键不存在,则不会引发异常。这就是为什么
remove
方法返回一个
boolean
,以指示是否实际删除了任何内容


但是,可以锁定局部变量。毕竟,您实际上是通过引用(以及与引用对象相关联的监视器)而不是变量锁定的,而另一个并发运行的方法将具有相同的引用。

ConcurrentHashMap
(通常是
Map
/
ConcurrentMap
)如果指定的键不存在,则不会引发异常。这就是为什么
remove
方法返回一个
boolean
,以指示是否实际删除了任何内容


但是,可以锁定局部变量。毕竟,您实际上是通过引用(以及与引用对象关联的监视器)而不是变量锁定的,而另一个并发运行的方法将具有相同的引用。

是的,这将很好地工作

您可以在java中的任何对象上进行同步,这样您的代码就可以工作,并且是线程安全的


从您没有检查t是否为空这一事实中可以看出。我猜您刚刚在代码示例中遗漏了这一点?

是的,这很好

您可以在java中的任何对象上进行同步,这样您的代码就可以工作,并且是线程安全的

从您没有检查t是否为空这一事实中可以看出。我猜您刚刚在代码示例中遗漏了这一点?

如果remove(null)将调用null指针异常,这似乎是合理的。如果您不认为冲突是一个常见的问题,那么您还可以实现一个可能更快的代码版本,只需围绕它包装一个try/catch,而不是一个synchronized

不管是哪种情况,我都会在这里添加一条注释来解释为什么要这样做,这样一个月后,它仍然是有意义的。

如果remove(null)会调用null指针异常,这似乎是合理的。如果您不认为冲突是一个常见的问题,那么您还可以实现一个可能更快的代码版本,只需围绕它包装一个try/catch,而不是一个synchronized


在任何一种情况下,我都会在这里添加一条注释来解释你为什么这么做,这样一个月后,它仍然是有意义的。

你可以锁定任何你想要的对象。然而,在您的情况下,看起来您可以更清楚、更安全地解决它

同步应尽可能本地化。由于您从某个未知位置获取
模板说唱程序
,因此任何人都有可能在其上进行同步,从而很难控制并发性。通过查看代码,也应该尽可能清楚地知道为什么某些东西会被锁定


最好将同步放在xlCache中,使用类似于
removiefinvalid()

的东西,您可以锁定任何想要的对象。然而,在您的情况下,看起来您可以更清楚、更安全地解决它

同步应尽可能本地化。由于您从某个未知位置获取
模板说唱程序
,因此任何人都有可能在其上进行同步,从而很难控制并发性。通过查看代码,也应该尽可能清楚地知道为什么某些东西会被锁定


最好使用类似于
removiefinvalid()

的方法将同步放在xlCache中。更好的方法是使用ConcurrentMap中的2 arg remove方法(假设t具有合理的equals实现)。那么您就不需要任何同步:

private Templates retrieveFromCache(String name) {
    TemplatesWrapper t = xlCache.get(name);

    if (!t.isValid()) {
        xlCache.remove(name, t);
        return null;
    }
    return t.getTemplate();
}

更好的方法是使用ConcurrentMap中的2 arg remove方法(假设t有一个合理的equals实现)。那么您就不需要任何同步:

private Templates retrieveFromCache(String name) {
    TemplatesWrapper t = xlCache.get(name);

    if (!t.isValid()) {
        xlCache.remove(name, t);
        return null;
    }
    return t.getTemplate();
}

在这种特定情况下,这可能是正确的,但您认为在本地(非字段)引用上同步是一个好主意吗?就我个人而言,我倾向于锁定一个私有的只读变量,但这取决于具体情况。@Jon给出的我的推理是否正确:“xlCache是一个concurrentHashMap,因此我从映射中获取包装,然后测试它是否有效,然后将其删除或从包装中返回模板”…是否存在线程交错的可能性(因为这是我首先同步的全部原因)…我的错误NullPointerException是在键为null而不是值的情况下引发的。完全正确-因此我认为首先不需要任何锁定。这正是我的想法,因为我的原始前提存在缺陷。是否存在这样的情况,即事情的时间安排使得
xlCache.remove(name)
会影响
TemplatesWrapper t=xlCache.get(名称)
给定的diff线程作用于该方法?在这种特定情况下,这可能是正确的,但您认为在本地(非字段)引用上同步是一个好方法吗