Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SMALLFIX]Avoid double synchronized #4812

Closed
wants to merge 2 commits into from

Conversation

maobaolong
Copy link
Contributor

No description provided.

@AmplabJenkins
Copy link

Merged build finished. Test PASSed.

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Alluxio-Pull-Request-Builder/13542/
Test PASSed.

@alluxio-bot
Copy link
Contributor

Automated checks report:

  • Valid pull request title: PASS
  • Commits associated with Github account: PASS

All checks passed!

@yupeng9
Copy link
Contributor

yupeng9 commented Feb 24, 2017

@maobaolong thanks for looking at it. Out of curiosity, how did you find the double synchronized issue? For example, did you hit deadlock or through profiling?

@maobaolong
Copy link
Contributor Author

@yupeng9 , Thanks for your review, I find this while debug alluxio, I know double sychronized doesn't cause deadlock there, I just think it is not necessary to mark the outer function synchronized.

@apc999
Copy link
Contributor

apc999 commented Feb 27, 2017

@maobaolong could you explain it a bit more details here? when you say outer functions, do you mean getFileInfo, getPinList and heartbeat these three methods? from what I see here, the thrift client they call here (e.g., mClient.getFileInfo, mClient.getPinIdList and mClient.heartbeat) is not thread safe. and that's why we want to make a thread-safe wrapper on the thrift client. Do I misunderstand something here?

@maobaolong
Copy link
Contributor Author

@apc999 as far as I know, the three functions getFileInfo, getPinList and heartbeat are all just call retryRPC function only, and the retryRPC function is thread safe, so the caller function needn't to make itself thread safe. Is that true?

@calvinjia
Copy link
Contributor

Would it make sense to make retryRPC not synchronized and make the other methods synchronized?

@maobaolong
Copy link
Contributor Author

make sense, and which way will be the better way? @ @calvinjia

@maobaolong
Copy link
Contributor Author

@calvinjia PTAL.

@AmplabJenkins
Copy link

Merged build finished. Test PASSed.

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Alluxio-Pull-Request-Builder/13622/
Test PASSed.

@calvinjia
Copy link
Contributor

@maobaolong Did you observe significant downside (ie. possible deadlock) or overhead for having the double synchronize? I don't think this should be expected (see: link)

@maobaolong
Copy link
Contributor Author

@calvinjia

The following test class was shown and solve many puzzled.

Let's diff myFourMethod myFiveMethod and my SevenMethod, after saw their bytecode, we can find that their bytecode were almost same, so java compiler help us do something.

So. the useless synchronized will not influence performance, just useless only.

package net.mbl.demo.concurrentdemo.synchrionzed;

/**
 * net.mbl.demo.concurrentdemo.synchrionzed <br>
 *
 * @author maobaolong@139.com
 * @version 1.0.0
 */
public class SyncTest {

  public static void main(String[] args) {
    final B b = new B();
    // A synchronized method in the superclass acquires the same lock as one in the subclass
    new Thread(){
      public void run(){
        int a=2;
        a++;
        b.myOneMethod();
        a--;
      }
    }.start();
    // Two synchronized method in the same instance acquires the same lock. In different critical
    // region.
    new Thread(){
      public void run(){
        int a=2;
        a++;
        b.myTwoMethod();
        a--;
      }
    }.start();
    new Thread(){
      public void run(){
        int a=2;
        a++;
        b.myThreeMethod();
        a--;
      }
    }.start();
    // A synchronized region in the same thread can re-entered.
    new Thread(){
      public void run(){
        int a=2;
        a++;
        b.myFourMethod();
        a--;
      }
    }.start();
    new Thread(){
      public void run(){
        int a=2;
        a++;
        b.myFiveMethod();
        a--;
      }
    }.start();
    new Thread(){
      public void run(){
        int a=2;
        a++;
        b.mySixMethod();
        a--;
      }
    }.start();
    new Thread(){
      public void run(){
        int a=2;
        a++;
        b.mySevenMethod();
        a--;
      }
    }.start();
  }
}

class A {
  public synchronized void myOneMethod(){
    System.out.println("{ myOneMethod");
    for(int i = 0; i < 10; i++){
      System.out.println("myOneMethod " + i);
      try {
        Thread.sleep(1000L);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    System.out.println("} myOneMethod");
  }
}
class B extends A {
  public synchronized void myTwoMethod(){
    System.out.println("{ myTwoMethod");
    for(int i = 0; i < 10; i++){
      System.out.println("myTwoMethod " + i);
      try {
        Thread.sleep(1000L);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    System.out.println("} myTwoMethod");
  }
  public synchronized void myThreeMethod(){
    System.out.println("{ myThreeMethod");
    for(int i = 0; i < 10; i++){
      System.out.println("myThreeMethod " + i);
      try {
        Thread.sleep(1000L);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    System.out.println("} myThreeMethod");
  }
  public synchronized  void myFourMethod(){
    System.out.println("{ myFourMethod");
    myOneMethod();
    System.out.println("} myFourMethod");
  }
  public void myFiveMethod(){
    System.out.println("{ myFiveMethod");
    myThreeMethod();
    System.out.println("} myFiveMethod");
  }
  public void mySixMethod(){
    System.out.println("{ mySixMethod");
    for(int i = 0; i < 10; i++){
      System.out.println("mySixMethod " + i);
      try {
        Thread.sleep(1000L);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    System.out.println("} mySixMethod");
  }
  public synchronized void mySevenMethod(){
    System.out.println("{ mySevenMethod");
    mySevenMethod();
    System.out.println("} mySevenMethod");
  }
}

The following are the bytecode of myFourMethod myFiveMethod and mySevenMethod.

 myFourMethod
 0 getstatic #2 <java/lang/System.out>
 3 ldc #20 <{ myFourMethod>
 5 invokevirtual #4 <java/io/PrintStream.println>
 8 aload_0
 9 invokevirtual #21 <net/mbl/demo/concurrentdemo/synchrionzed/B.myOneMethod>
12 getstatic #2 <java/lang/System.out>
15 ldc #22 <} myFourMethod>
17 invokevirtual #4 <java/io/PrintStream.println>
20 return

myFiveMethod
 0 getstatic #2 <java/lang/System.out>
 3 ldc #23 <{ myFiveMethod>
 5 invokevirtual #4 <java/io/PrintStream.println>
 8 aload_0
 9 invokevirtual #24 <net/mbl/demo/concurrentdemo/synchrionzed/B.myThreeMethod>
12 getstatic #2 <java/lang/System.out>
15 ldc #25 <} myFiveMethod>
17 invokevirtual #4 <java/io/PrintStream.println>
20 return

mySevenMethod
 0 getstatic #2 <java/lang/System.out>
 3 ldc #29 <{ mySevenMethod>
 5 invokevirtual #4 <java/io/PrintStream.println>
 8 aload_0
 9 invokevirtual #30 <net/mbl/demo/concurrentdemo/synchrionzed/B.mySixMethod>
12 getstatic #2 <java/lang/System.out>
15 ldc #31 <} mySevenMethod>
17 invokevirtual #4 <java/io/PrintStream.println>
20 return

@maobaolong maobaolong closed this Mar 3, 2017
@apc999
Copy link
Contributor

apc999 commented Mar 7, 2017

@maobaolong thanks for the investigation by analyzing JVM bytecodes. Your experiment is quite educational. Thanks

@maobaolong maobaolong deleted the mbl-patch-sync branch December 25, 2017 17:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants