0

Hi I have a class with multiple methods in which I require synchronized blocks in all of the methods like this:

public class Test2 { private Object mutex=new Object(); private OtherClass obj=new OtherClass(); public void method1(){ //do some stuff synchronized (mutex) { obj.//some method //do some stuff } //do other stuff } public void method2(){ //do some stuff synchronized (mutex) { obj.//some method //do some stuff } //do other stuff } public void method3(){ //do some stuff synchronized (mutex) { obj.//some method //do some stuff } //do other stuff } public void method4(){ //do some stuff synchronized (mutex) { obj.//some method //do some stuff } //do other stuff } } 

I am using mutex to synchronize the blocks, so what happens if method1 is being used, the other method2 synchronized block waits until the flow comes out of the synchronized block of method1.

I dont want this to happen, so what should i do? I know that as I am using mutex for all the methods, so it locks the method2 synchronized block. I want to know what should I do to remove this? Should I create member variables for each method to use, or is there another way around this?

I want the other thread to wait only if the same method is called.. like if two threads class mehod1 so the second thread should wait. but if the second thread calls method2 it should not wait.

9
  • If that is not the behaviour you want, what do you want method2 to do? Skip the block? Then synchronized is not what you are looking for... Commented Jun 29, 2012 at 12:38
  • i want the other thread to wait only if the same method is called.. like if two threads class mehod1 so the second thread should wait. but if the second thread calls method2 it should not wait. Commented Jun 29, 2012 at 12:41
  • Down-voted - very localized question, the answer is so trivially obvious even the author suggests it in the question. Commented Jun 29, 2012 at 12:44
  • 2
    @Romain Well, he asks if there is a better way. The answer might be trivial to you, but its not correct to assume that the answer is obvious for everyone... Commented Jun 29, 2012 at 12:48
  • @brimborium It would be incorrect to assume so if Google and StackOverflow didn't already answer the question half a billion times in one way or another. Problem is they do. Commented Jun 29, 2012 at 12:52

4 Answers 4

4

Judging by your comment I assume you want per-method synchronization instead of per-object. In this case the simplest way would be to declare a separate monitor object for each method i.e. mutex1, mutex2, etc.

Sign up to request clarification or add additional context in comments.

8 Comments

so you mean that if i have around 20 methods? i should have 20 mutex objects? isn't there any other way around this?
Well you could declare an array of 20 objects like Object[] mutexes = new Object[20]; and use a different index for each method, so you don't declare 20 class members.
@Dennis: Since each thread has its own private stack, declaring them locally will make each thread see a different mutex, which would be useless. They need to be globally visible.
hey but Object[] mutexes = new Object[20]; is causing a null pointer..?? after using its index?
@Dennis you have to init the array
|
4

You should use another mutext in the method2 method.

1 Comment

so you mean that if i have around 20 methods? i should have 20 mutex objects? isn't there any other way around this?
2

Just use different monitors for every method.

public class Test2 { private Object mutex1 = new Object(), mutex2 = new Object(); private OtherClass obj=new OtherClass(); public void method1() { //do some stuff synchronized (mutex1) { obj.//some method //do some stuff } //do other stuff } public void method2() { //do some stuff synchronized (mutex2) { obj.//some method //do some stuff } //do other stuff } } 

If you have a lot of methods, you can also pack them in an array.

3 Comments

can these be local variables also or they wont work ? they have to be member variables?
@Dennis local variables would not work as every invocation of the method gets its own local variables.
@Dennis They can not be local variables as those would be created new at every method call. The synchronization would not work that way...
2

You have to use different monitor objects (mutex in your code) for each method call if you want to achieve this and synchornize to them. If you have many methods, you could use some kind of collection to hold your mutex objects:

public class Test2 { private Object[] mutexes=new Object[2]; private OtherClass obj=new OtherClass(); private synchronized Object getMutex(int i) { if(mutexes[i] == null) { mutexes[i] = new Object(); } return mutexes[i]; } public void method1(){ //do some stuff synchronized (getMutex(1)) { //do some stuff } //do other stuff } public void method2(){ //do some stuff synchronized (getMutex(2)) { //do some stuff } //do other stuff } } 

Note that if you synchronize on a per method basis but each method accesses the same object (obj in your case) from the synchronized blocks, the access to that specific object is still not thread-safe.

The other option would be to initialize all mutexes in the constructor instead of creating them on-demand in the getMutex() method:

public Test() { for(int i = 0; i < mutexes.length()) { mutexes[i] = new Object(); } } 

3 Comments

You need the getMutex(int) method to be synchronized (or use a synchronized double-check on mutexes), or two calls could obtain two distinct mutexes. (A checks, A allocates the mutex, B other checks, A assigns the mutex, B allocates the mutex, KABOOOM).
@Romain: You're right, I've updated the example. The other option would be to initialize all mutexes before the method calls (eg. in the Test2 constructor) then the null-check would not be necessary at all.
Yes indeed. Something like private final Object[] mutexes = {new Object(), new Object()}; would do the job nicely.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.