简体   繁体   English

令人困惑的Java同步方法,synced(this)和synced类

[英]Confusing Java synchronized method, synchronized(this), and synchronized class

I'm very confused because of Java's synchronized concept. 由于Java的同步概念,我感到非常困惑。

Let's assume the below class: 让我们假设下面的类:

class MyClass {
  public synchronized void foo() { //do something }
  public void bar() {
    synchronized(this) { //do something }
  }
  public void normal() { //do something }
}

As far as I know, the foo and bar methods work the same. 据我所知, foobar方法的工作原理相同。

But, after thread A enters the bar method and synchronizes the instance by synchronized(this) , can any thread call the normal method? 但是,在线程A进入bar方法并通过synchronized(this)同步实例之后,任何线程都可以调用普通方法吗?

As far as I know, some threads can call the normal method regardless of calling the foo method. 据我所知,某些线程可以调用普通方法,而无需调用foo方法。 But I'm not sure when the bar method is called because it synchronized an instance. 但是我不确定何时调用bar方法,因为它同步了一个实例。

Also, let's assume the below method: 另外,我们假设以下方法:

class StaticMyClass {
  public static synchronized void fooStatic() { //do something }
  publi static void barStatic() {
    synchronized(StaticMyClass.class) { //do something }
  }
  public static void normalStatic() { //do something }
}

Here, there is the same question. 在这里,有同样的问题。 After thread A enters the critical section, which is synchronized(StaticMyClass.class) or the fooStatic method, can any thread call normalStatic ? 线程A进入关键部分(已synchronized(StaticMyClass.class)fooStatic方法)之后,任何线程都可以调用normalStatic吗?
I think that fooStatic and normalStatic can be called independently, but barStatic and normalStatic can't. 我认为fooStaticnormalStatic可以独立调用,但是barStaticnormalStatic不能。 If it is wrong, why? 如果不对,为什么?

I appreciate your help. 我感谢您的帮助。

Edit: 编辑:
My confused point is that I am not sure that synchronized(this) is same as synchronized(myClassInstance) . 我的困惑点是我不确定synchronized(this)是否与synchronized(myClassInstance)相同。

MyClass my = new MyClass();
synchronized(my) {
  //do something, Any other thread can't access my.normal(), is it right?
}

class MyClass {
  public synchronized void foo() { //do something }
  public void bar() {
    synchronized(this) {
      //do something, isn't this same as above synchronized(my)?
    }
  }
  public void normal() { //do something }
}

As far as I know, foo and bar methods work same. 据我所知, foobar方法的工作原理相同。

Correct. 正确。 They both synchronize on this . 他们都与this同步。

After thread A enter the bar method and synchronize the instance by synchronized(this) , can any thread call normal method? 在线程A进入bar方法并通过synchronized(this)同步实例之后,任何线程都可以调用normal方法吗?

Yes. 是。 Correct. 正确。

As far as I know, some thread can call normal method regardless calling foo method. 据我所知,某些线程可以调用normal方法,而无需调用foo方法。 but I'm not sure when the bar method is called. 但是我不确定何时调用bar方法。 because it synchronized a instance. 因为它同步了一个实例。

foo and bar are the same. foobar相同。 They are both synchronizing on this . 他们在两个同步this The normal method is not synchronizing on anything. normal方法是不同步任何东西。 Therefore it can be called at any time from anywhere and it will not blocked, either at the point of the method call, or internally. 因此,可以随时随地调用它,并且在方法调用时或在内部都不会阻塞。

In your terminology, the normal method is not a critical section 1 . 用您的术语来说, normal方法不是关键部分1


Second example with statics 静电的第二个例子

Here, there is same question. 在这里,有同样的问题。 after thread A enter the critical section which is synchronized(StaticMyClass.class) or fooStatic method, can any thread call normalStatic ? 在线程A进入已synchronized(StaticMyClass.class)的关键部分synchronized(StaticMyClass.class)fooStatic方法之后,任何线程都可以调用normalStatic吗?

Yes. 是。 The fooStatic and barStatic will both synchronize on StaticMyClass.class . fooStaticbarStatic都将在StaticMyClass.class同步。

I think, call fooStatic and normalStatic can be called independently, but barStatic and normalStatic can't. 我认为,可以分别调用fooStaticnormalStatic ,但不能单独调用barStaticnormalStatic

Incorrect. 不正确。 The normalStatic is not blocked by fooStatic OR barStatic . normalStatic是不会被fooStatic OR barStatic

I'm not sure where you got the idea that normalStatic might be blocked ... but it is a normal method call and doesn't acquire any intrinsic locks, so it cannot be blocked on a lock. 我不确定在哪里可以知道normalStatic可能被阻止了……但是这是一个普通的方法调用,并且不会获取任何内部锁,因此无法在锁上对其进行阻止。


Your third example is unclear. 您的第三个示例尚不清楚。 The code shows one thing, but the question asks something different / unrelated. 代码显示了一件事,但是问题提出了不同/无关的问题。


1 - It might get a bit confusing if (say) foo or bar called normal while holding the intrinsic lock. 1-如果(例如) foobar保持固有锁定时被称为normal ,可能会引起混淆。 Then the normal code will be effectively in the critical section because the caller holds the lock . 然后, 由于调用者持有该锁,因此normal代码将有效地位于关键部分。 But it ( normal ) typically won't know this. 但这( normal )通常不知道这一点。 This is why I prefer to avoid the "critical section" terminology. 这就是为什么我宁愿避免使用“关键部分”术语的原因。

If you do not specify who is the monitor, with instance methods the monitor is the instance (this), and with static methods the monitor is the class (YourClass.class). 如果未指定监视器是谁,则使用实例方法,监视器是实例(this),使用静态方法,监视器是类(YourClass.class)。

This code 此代码

public synchronized void foo() { //do something }

It is the same than this 比这个一样

public void foo() {
   synchronized(this) { //do something }
}

and this code 和这段代码

public static synchronized void fooStatic() { //do something }

is the same than this 与此相同

public static void fooStatic() {
   synchronized(StaticMyClass.class) { //do something }
}

So, in both cases, foo and bar are dependant (only one thread at the same time), while normal can be called independently. 因此,在两种情况下,foo和bar都是相关的(同一时间仅一个线程),而normal可以独立调用。

but After thread A enter the bar method and synchronize the instance by synchronized(this), Can any thread call the normal method? 但是在线程A进入bar方法并通过synced(this)同步实例之后,任何线程都可以调用普通方法吗?

It is not possible for two invocations of synchronized methods on the same object to interleave. 在同一个对象上两次同步方法调用是不可能交织的。 When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object. 当一个线程正在执行对象的同步方法时,所有其他调用同一对象块的同步方法的线程(挂起执行),直到第一个线程对该对象完成。

If you are trying to call other methods which aren't synchronized, then it is possible. 如果您尝试调用其他不同步的方法,则可以。

after thread A enter the critical section which is synchronized(StaticMyClass.class) or fooStatic method, can any thread call normalStatic? 在线程A进入已同步的关键部分(StaticMyClass.class)或fooStatic方法之后,任何线程都可以调用normalStatic吗? I think, call fooStatic and normalStatic can be called independently, but barStatic and normalStatic can't. 我认为,可以分别调用fooStatic和normalStatic,但不能单独调用barStatic和normalStatic。 if it is wrong why? 如果错了为什么?

The other methods which are not synchronized can be called independently, but when you call the barStatic() it is not possible for the other methods to be called, as you are synchronizing the entire class. 可以独立调用其他未同步的方法,但是当您调用barStatic()时,由于正在同步整个类,因此无法调用其他方法。 other threads, have to wait until the current thread is finished executing. 其他线程,必须等到当前线程完成执行。

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

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