How do I conditionally lock in Java?

元气小坏坏 提交于 2020-01-14 05:03:14

问题


I have been making use of Java's synchronized blocks to make parts of my code thread safe. I am porting a data structure to java that can usually use synchronized blocks, but I don't always know how to use them in a typical Java way.

Here is an example of one scenario:

myMethod (Bool useLock)
    {
    if (useLock)
        {
        //locks the following section of code until unlocked.
        lockObject.lock();
        }

     //do more stuff....

    if (useLock)
        {
        //unlocks exclusive control of code.
        lockObject.unlock();
        }
     }

How do I do an equivalent of this in Java? In this code sometimes I want to lock and sometimes I don't, but I want to be smart about it and not have to write two versions of the same code. Are there other ways of locking in Java other than using synchronized blocks?


回答1:


You can use Lock objects, ReentrantLock in particular should do the work. http://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.html

Or you can still solve the issue with synchronized blocks. The code from your question will look like:

myMethod (Bool useLock) {
    if (useLock) {
        synchronized (this) {
           criticalSection();
        }
    } else {
        criticalSection();
    }
}

criticalSection() {
   //do more stuff....
}

Or if you want to guarantee the mutual exclusion among different instances of the class you should use other monitor object than this. For instance TheClassName.class or other explicitly defined static variable of that class.




回答2:


Some good answers already posted, but I wanted to add another solution that worked for me:

I started with:

...
synchronized(<lockobject>) {
 <huge section of code with lots of variables>
}
...

Changed it to:

...
synchronized(<condition> ? <lockobject> : new Object()) {
 <huge section of code with lots of variables>
}
...

Basically if the condition is true it executes the code using synchronized on lockobject, but if the condition is false it uses "new Object()" which basically lets it run without any synchronization.




回答3:


I Guess ReentrantLock can be used in your scenario

final Lock lock = new ReentrantLock();

Sample code snippet

class X {
private final ReentrantLock lock = new ReentrantLock();
 // ...

 public void m() { 
   lock.lock();  // block until condition holds
   try {
   // ... method body
   } finally {
   lock.unlock()
    }
  }
 }



回答4:


You can use Unsafe to monitorEnter and monitorExit but this is a bad idea IMHO.

If the locks are not needed the JVM will almost optimise them away in any case. synchronized is very efficient if only one thread ever acquires it. (Unlike Lock for example)




回答5:


Are there other ways of locking in Java other than using synchronized blocks?

Yes - java.util.concurrent.locks, and the ReentrantLock class in particular, but as Peter says if you can get away with just using synchronized it'll probably be more efficient overall (and easier to maintain, particularly if you're working as part of a team).




回答6:


You can use Java lock objects and Condition objects. Condition class' java docs gives a very good isFull and isEmpty example too.

In your case, i guess, you can utilise the condition object to make the code more readable/understandable. something like this:

 final Lock lock = new ReentrantLock();
 final Condition useLock  = lock.newCondition(); 

and use the condition as appropriate.



来源:https://stackoverflow.com/questions/12534364/how-do-i-conditionally-lock-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!