简体   繁体   English

同步方法

[英]Synchronized Methods

If I have a synchronized public method and a private method: 如果我有一个同步的公共方法和私有方法:

public synchronized void doSomething() {
    doSomethingElse()
}

private void doSomethingElse() {
}

Do I need to synchronize the private method? 我需要同步私有方法吗?

It depends: 这取决于:

  • If doSomethingElse is safe to call concurrently, then you don't need synchronized . 如果doSomethingElse可以安全地同时调用,那么您不需要synchronized
  • If it isn't, then the answer depends on where it is called from: 如果不是,那么答案取决于它的调用位置:
    • If it is only called from other synchronized methods, then it doesn't need to be synchronized (but marking it as such will do no harm); 如果仅从其他synchronized方法调用它,则不需要synchronized (但是将其标记为不会造成伤害);
    • If it can be called from methods that aren't synchronized themselves, then it must be synchronized . 如果可以从不synchronized方法调用它,则必须 synchronized它。

It depends on what you're doing. 这取决于你在做什么。 Do you need to ensure serial access to doSomethingElse() ? 您是否需要确保对doSomethingElse()串行访问?

If so, and the only thing calling doSomethingElse() is doSomething() , then no, you don't need to synchronize. 如果是这样,并且调用doSomethingElse()的唯一事情是doSomething() ,那么不,你不需要同步。 But if some other method can call doSomethingElse() , then yes, you should synchronize it also. 但是如果其他一些方法可以调用doSomethingElse() ,那么是的,你也应该同步它。

NO: if the only way doSomethingElse() is called is through another method that IS synchronized. NO:如果调用doSomethingElse()的唯一方法是通过另一个IS同步的方法。

Possibly YES: If you call doSomethingElse() in some other fashion, through a method that is not synchronized, and you need to protect it against concurrent access. 可能是:如果以其他方式调用doSomethingElse() ,则通过未同步的方法,并且需要保护它免受并发访问。

This is the intent of the @GuardedBy annotation. 这是@GuardedBy注释的意图。 If you expect that a lock must be held when calling that method, annotate it with that and the name of the lock (in the example it would be: 如果您希望在调用该方法时必须保持锁定,请使用该方法和锁定名称对其进行注释(在示例中它将是:

@GuardedBy("this") private void doSomethingElse() {…}

Then you can check that the invariant is true with FindBugs. 然后你可以检查FindBugs的不变量是否为真。

You can also use the other net.jcip.annotations for describing the thread-safety or lack of it and have FindBugs validate these assumptions too. 您还可以使用其他net.jcip.annotations来描述线程安全性或缺少线程安全性,并让FindBugs验证这些假设。 Of course, the book needs a plug as well. 当然, 这本书也需要一个插件。

Any methods called from a synchronized method (or from within a synchronized block) are run while still synchronized. 从同步方法(或从synchronized块内)调用的任何方法在仍然同步的情况下运行。 You don't need to separately synchronize the private method if it is only called from synchronized methods. 如果仅从同步方法调用私有方法,则不需要单独同步私有方法。

Even though the code works correctly when the private method is not synchronized, it would seem prudent from a maintainability perspective to make the private method synchronized. 即使代码在私有方法未同步时正常工作,从可维护性角度来看,使私有方法同步似乎也是谨慎的。

Intrinsic locks are re-entrant, there is no harm in adding the synchronized keyword to the private method. 内部锁是可重入的,将synchronized关键字添加到私有方法没有任何害处。

Putting code in a private method invites letting it be called by other methods, so it would make sense to make the private method synchronized in case in the future it is called from another method that does not otherwise need to be synchronized. 将代码放在私有方法中会让它被其他方法调用,因此将私有方法同步以备将来从另一个方法调用它是有意义的,否则需要同步。

If you synchronize a block of code then anything called from within that block of code (on the same thread) still holds the initial lock. 如果您同步一个代码块,那么从该代码块(在同一个线程上)调用的任何内容仍然保持初始锁定。 So doSomethingElse is still a part of the synchronized block when it is called from doSomething . 因此doSomethingElse在从doSomething调用时仍然是synchronized块的一部分。

If you did: 如果你这样做:

public synchronized void doSomething() {
  new Thread() {
    public void run() {
      doSomethingElse();
    }
  }.start();
}
private void doSomethingElse() {
}

Then doSomethingElse would not have the lock that was acquired by doSomething . 然后doSomethingElse没有 doSomething获取的锁。

Also avoid synchronized methods as it exposes the implementation details of your concurrency policy. 还要避免使用同步方法,因为它暴露了并发策略的实现细节。 See this question on synchronized(this) / synchronized methods: Avoid synchronized(this) in Java? 请参阅有关synchronized(this)/ synchronized方法的这个问题: 避免在Java中同步(this)?

If doSomethingElse must be synchronized, regardless of whether or not it is called from doSomething , it wouldn't hurt to synchronize doSomethingElse as synchronized locks are re-entrant (ie, if a thread already has a lock on an object it can get the lock again). 如果必须同步doSomethingElse ,无论是否从doSomething调用它,同步doSomethingElse都不会doSomethingElse因为同步锁是可重入的(即,如果一个线程已经锁定了一个对象,它就可以获得锁定再次)。

Personally, I do not like synchronized methods. 就个人而言,我不喜欢同步方法。 I prefer to synchronize with some kind of lock varaible, as so: 我更喜欢与某种锁定变量同步,如下所示:

private final Object lock = new Object();

public void doSomething() {
  synchronized(lock) {
    // Do some safely
    doSomethingElse();
  }
  // Do some work un-safely
}

private void doSomethingElse() {
  // Do some work safely because still in lock above
  // ...
}

Although what you've done is fine, in my opinion, synchronization should be done at the lowest granularity possible. 虽然你所做的很好,但在我看来,同步应尽可能以最低的粒度进行。 Which would suggest to synchronize the actual private function. 这将建议同步实际的私人功能。 Currently, you're assuming that no other function in the class will call the private function independently. 目前,您假设类中没有其他函数可以独立调用私有函数。 This may not be the case in the future. 将来情况可能并非如此。

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

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