2

I have a question about the behavior of the following type of code

public synchronized < T > List< T > executeSelect(Class< T > c) { }

If I execute the code queryEngine.executeSelect(A.class); in one thread and queryEngine.executeSelect(B.class); in another thread do those threads treat the method as one (and one waits for another) or two different and they are executed concurrently?

I want to have a DB query engine that is behind a web service and returns object of a given type from a database. I also want to use just one connection to the database and open / close it for query execution.

VoytechM
  • 65
  • 6
  • try this: set a break point in execute select. this will tell you if there are two executeSelect() methods (like in C) or only one executeSelect() method. – DwB Jul 03 '14 at 12:09

3 Answers3

2

The synchronized modifier leads to the methods being executed after acquiring an implicit monitor which is released after the method returns. This monitor is:

  • The instance the method is executed on for a non-static method
  • The class the method is defined for for a static method

You can therefore translate your non-static method

public synchronized <T> List<T> executeSelect(Class<T> c) { 
  // code
}

to

public <T> List<T> executeSelect(Class<T> c) { 
  synchronized(this) {
    // code
  }
}

As a matter of fact, the JRockit VM even applied this translation internally and I suspect the HotSpot VM to do the same.

Thus, it does not matter if the method is run with a specific generic argument (especially since the runtime is not aware of generic types which are erased after compilation) or even which non-static method is executed on an instance as any method acquires the very same monitor. It is only the instance on which a method is called that determines which monitor the synchronized modifier implicitly refers to.

Rafael Winterhalter
  • 38,221
  • 13
  • 94
  • 174
0

Generic method does not result in multiple implementations. Due to type erasure it is equivivalent to a single synchronized List executeSelect(Class) method and this method is used by both threads regardless of specific parameter types.

So usual rules of calling synchronized method on the same instance apply - multiple threads will not be able to execute it concurrently.

You can read more about type erasure in this and this question and follow links provided in them.

Community
  • 1
  • 1
Oleg Estekhin
  • 7,168
  • 5
  • 47
  • 51
0

Generics are only for compile time so runtime it behaves like just another syncronized method.

public synchronized < T > List< T > executeSelect(Class< T > c) { } 

will be compiled to

public synchronized List executeSelect(Class c) { } 

It is just that compile time if you call the method like below that compiler will know that you are passing incorrect type as argument.

List<String> = obj.<String>executeSelect(new Integer(1));
bitkot
  • 4,318
  • 2
  • 25
  • 38