简体   繁体   English

同步关键字-如何运作?

[英]Synchronized keyword- how it works?

If I have a class, call it X and X contains a collection (assume I am not using one of the synchronized colections, just a normal one). 如果我有一个类,则称它X并且X包含一个集合(假设我没有使用同步集合之一,只是一个普通集合)。

If I was to write my own method synchronized add()- how does the locking work? 如果要编写自己的方法,则同步的add()-锁定如何工作? Is the locking done on the instance of X, and not on the collection object? 锁定是否在X实例上完成,而不在集合对象上完成?

So synchronizing my add() method would not stop many instances of X from calling add() and inserting into the collection- therefore I could still have threading problems? 因此,同步我的add()方法不会阻止X的许多实例调用add()并将其插入集合中-因此,我仍然可能遇到线程问题吗?

A synchronized method locks the object. 同步方法锁定对象。 If your X.add is synchronized, it will prevent concurrent execution of other synchronized methods of the same X object. 如果您的X.add是同步的,它将阻止并发执行同一X对象的其他同步方法。 If anyone out of that X object has access to the same collection, the collection will not be protected. 如果该X对象之外的任何人都可以访问同一集合,则该集合将不受保护。

If you want your collection to be protected, make sure it is not accessible to the rest of the world in any way other than a synchronized method of X . 如果要保护您的集合,请确保除X的同步方法外,其他任何地方都无法访问它。 Also, this is a bit unclear in your question, but note that a synchronized non-static method locks the object . 此外,这在您的问题中还不清楚,但是请注意,同步的非静态方法会锁定对象 Assuming each X instance will have a collection of its own, they won't interfere with each other. 假设每个X实例都有自己的集合,它们不会互相干扰。

Another option, BTW, is to lock the collection instead of the X object: 另一个选项BTW是锁定集合而不是X对象:

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

This will synchronize access to the locked collection instead of the X object. 这将同步对锁定集合而不是X对象的访问。 Use whichever you find easier and more effective. 使用任何您发现更容易有效的方法。

In your example, synchronized will make sure only one thread can invoke the method on one instance of the class at a time. 在您的示例中, synchronized将确保一次只能有一个线程可以在该类的一个实例上调用该方法。 Other methods could access that collection, which would not be safe. 其他方法可以访问该集合,这将是不安全的。 Look up concurrent collections for more information on thread-safe collection implementations. 查找并发集合以获取有关线程安全集合实现的更多信息。

If I was to write my own method synchronized add()- how does the locking work? 如果要编写自己的方法,则同步的add()-锁定如何工作? Is the locking done on the instance of X, and not on the collection object? 锁定是否在X实例上完成,而不在集合对象上完成?

The locking is done on the object that you synchronized on -- not any fields within the object. 锁定是在您同步的对象上完成的,而不是对象内的任何字段。 For locking to work, all of the threads must synchronize on the same exact object. 为了使锁定起作用,所有线程必须在同一确切对象上同步。 Typically a private final object is best to be locked on. 通常,最好将private final对象锁定。

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

Although a common pattern is to lock on the object that you are protecting, it really can be any constant object. 尽管常见的模式是锁定要保护的对象,但实际上它可以是任何常量对象。 You could also do: 您也可以这样做:

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

So synchronizing my add() method would not stop many instances of X from calling add() and inserting into the collection- therefore I could still have threading problems? 因此,同步我的add()方法不会阻止X的许多实例调用add()并将其插入集合中-因此,我仍然可能遇到线程问题吗?

If other parts of your application are accessing the myCollection without being inside of a synchronized (myCollection) block, then yes, you are going to have threading problems. 如果应用程序的其他部分正在访问myCollection 而不位于synchronized (myCollection)块内部,则可以,您将遇到线程问题。 You would need to synchronize around all accesses to properly protect the collection and provide a memory barrier. 您需要围绕所有访问进行同步,以正确保护集合并提供内存屏障。 That means add(...) , contains(...) , iterators, etc.. 这意味着add(...)contains(...) ,迭代器等。

Often, if you are trying to protect a collection or other class, it makes sense to wrap it in a class which does the synchronization. 通常,如果您试图保护集合或其他类,则将其包装在进行同步的类中是很有意义的。 This hides the locking and protects the collection from unintended modifications from code that is missing a synchronized block. 这将隐藏锁定,并保护集合免受丢失synchronized块的代码的意外修改。

Is it true that you are sharing one collection across many X instances ? 您是否在多个X实例上共享一个集合 ,这是真的吗? Then you need to synchronize on the collection instance itself. 然后,您需要在集合实例本身上进行同步。 Don't make the method itself synchronized , but wrap all its code in a synchronized(coll) { ... } block. 不要使方法本身synchronized ,而是将其所有代码包装在synchronized(coll) { ... }块中。

If, on the other hand, each X has its own collection, then synchronized add() is all you need. 另一方面,如果每个X都有自己的集合,那么您只需要synchronized add() This will guarantee that no two threads are executing add on the same instance at the same time. 这将确保没有两个线程同时在同一实例上执行add

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

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