繁体   English   中英

同步关键字-如何运作?

[英]Synchronized keyword- how it works?

如果我有一个类,则称它X并且X包含一个集合(假设我没有使用同步集合之一,只是一个普通集合)。

如果要编写自己的方法,则同步的add()-锁定如何工作? 锁定是否在X实例上完成,而不在集合对象上完成?

因此,同步我的add()方法不会阻止X的许多实例调用add()并将其插入集合中-因此,我仍然可能遇到线程问题吗?

同步方法锁定对象。 如果您的X.add是同步的,它将阻止并发执行同一X对象的其他同步方法。 如果该X对象之外的任何人都可以访问同一集合,则该集合将不受保护。

如果要保护您的集合,请确保除X的同步方法外,其他任何地方都无法访问它。 此外,这在您的问题中还不清楚,但是请注意,同步的非静态方法会锁定对象 假设每个X实例都有自己的集合,它们不会互相干扰。

另一个选项BTW是锁定集合而不是X对象:

void add(Object o) {
   synchronized(myCollection) {
      myCollection.add(o);
   }
}

这将同步对锁定集合而不是X对象的访问。 使用任何您发现更容易有效的方法。

在您的示例中, synchronized将确保一次只能有一个线程可以在该类的一个实例上调用该方法。 其他方法可以访问该集合,这将是不安全的。 查找并发集合以获取有关线程安全集合实现的更多信息。

如果要编写自己的方法,则同步的add()-锁定如何工作? 锁定是否在X实例上完成,而不在集合对象上完成?

锁定是在您同步的对象上完成的,而不是对象内的任何字段。 为了使锁定起作用,所有线程必须在同一确切对象上同步。 通常,最好将private final对象锁定。

    private final Collection<...> myCollection = ...
    ...
    synchronize (myCollection) {
        myCollection.add(...);
    }

尽管常见的模式是锁定要保护的对象,但实际上它可以是任何常量对象。 您也可以这样做:

    private final Object lockObject = new Object();
    ...
    synchronize (lockObject) {
        myCollection.add(...);
    }

因此,同步我的add()方法不会阻止X的许多实例调用add()并将其插入集合中-因此,我仍然可能遇到线程问题吗?

如果应用程序的其他部分正在访问myCollection 而不位于synchronized (myCollection)块内部,则可以,您将遇到线程问题。 您需要围绕所有访问进行同步,以正确保护集合并提供内存屏障。 这意味着add(...)contains(...) ,迭代器等。

通常,如果您试图保护集合或其他类,则将其包装在进行同步的类中是很有意义的。 这将隐藏锁定,并保护集合免受丢失synchronized块的代码的意外修改。

您是否在多个X实例上共享一个集合 ,这是真的吗? 然后,您需要在集合实例本身上进行同步。 不要使方法本身synchronized ,而是将其所有代码包装在synchronized(coll) { ... }块中。

另一方面,如果每个X都有自己的集合,那么您只需要synchronized add() 这将确保没有两个线程同时在同一实例上执行add

暂无
暂无

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

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