繁体   English   中英

锁定对象实例上的java…安全吗?

[英]java locking on an object instance … is this safe?

我的问题是关于锁定Java中的对象实例。 我有以下方法,可以同时由多个线程调用。 我选择锁定一个对象实例,因为我希望允许并发处理,只要一次仅一个线程访问一个实例即可。

我的简化代码是这样的,基本上我锁定了局部变量。 这真的可以满足我的需求吗? 我一直在阅读建议,永远不要锁定可能会更改的对象,而我突然不确定这到底是我在做什么!

谢谢!

编辑:

哦,亲爱的...我只是意识到我试图简化代码以便发布的尝试可能会产生误导。

我将以前称为“ getInstance”的方法重命名为其他名称(“ getFromMap”),以演示该方法调用是自定义代码,该代码返回对哈希图中对象的引用。

先前的答案还会成立吗? 对此表示歉意!

public boolean processInput(...) {
if(message == 1) {
    Class_0 context = (Class_0)Class_0.getFromMap("xyz");
    synchronized(context) {
        context.setContextParams("abc");
       context.evaluateContextRules(message, this);
    }
} else if(message == 2) {
    Class_1 context = (Class_1)Class_1.getFromMap("efg");
    synchronized(context) {
        context.setContextParams("abc");
        context.evaluateContextRules(message, this);
    }
}
.....
}

对象类型的变量只是对对象的引用 是锁定的对象 ,而不是引用。 只有当所有可能读取或写入相关数据的客户端都同意这样做(并且仅当该对象拥有该锁时),这样的锁才有效。 不管它是否是局部变量都没关系-所有人是否都使用与锁相同的对象。

在这里,您的对象似乎来自某种工厂。 如果getInstance(X)对于给定的X值始终返回相同的对象,则可能很好。

假如说:

Class_1 context = (Class_1)TestForInternals_0.getInstance("efg");

只需检索对现有对象的引用,而不会创建新实例,则该对象的监视器将被锁定,并且您正在执行的操作是有效的。

您的问题中确实没有足够的“上下文”(不需要双关语)来确定此代码是否完全是线程安全的。

但是,如果我们假设1) message是局部变量,并且2)访问或更新上下文对象的所有操作都在该对象上进行同步时这样做,则该片段中的代码是线程安全的。


我一直在阅读建议,永远不要锁定可能会更改的对象,而我突然不确定这到底是我在做什么!

您应该担心的是这样的事情:

public class Foo {
    // some state variables

    public Object lock = new Object();

    public void doSomething(...) {
        synchronized (lock) {
            ....
        }
    }
}

这可能是不安全的。 如果在适当的时间更改了lock的值,并且对同一个Foo实例的两个操作最终可能会使用不同的锁对象进行同步。 这可能导致涉及Foo状态的操作无法正确同步。

在您的示例中, context同步似乎是针对上下文对象本身的操作,因此上述问题不适用。

只要您对context所做的修改不影响getInstance方法返回的内容,您的代码就可以工作

据我了解,您的方法processInput被调用,并且您的同步块确保context.evaluateContextRules(...)仅在一个线程中运行。

如果这是您的目标,那么可以,您的代码可以做到这一点。

其他人提到您必须确保锁定对象,而不是对对象的引用。 好吧,正如在代码中所看到的那样,您正在对调用方法的同一对象进行同步,所以这不应该成为问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM