How to skip method if some thread owns by this method in java, i know that in .net exists Monitor.TryEnter, and i can accomplish that by something like this:
if(Monitor.TryEnter()){
//do work
}
//else skip
But how can i accomplish that behavior in java, is any equivalent of Monitor.TryEnter in java.
Would ReentrantLock#tryLock() work for you?
It has the behavior that you want, but it requires an explicit lock object and as such it does not work with the embedded Java object monitor - I do not believe that there is an equivalent to tryLock() for Java object monitors.
I think you're probably best off using java.util.concurrent.Semaphore.
If you use a Semaphore that holds one permit :
Semaphore semaphore = new Semaphore(1);
the resulting code looks virtually the same :
if (semaphore.tryAcquire()) {
try {
// do work
} finally {
semaphore.release();
}
}
// else skip
I imagine in .Net you also have to make sure to release the lock again.
Related
I was looking through the source code for DatagramSocket and I found this:
public void disconnect() {
synchronized (this) {
if (isClosed())
return;
if (connectState == ST_CONNECTED) {
impl.disconnect ();
}
connectedAddress = null;
connectedPort = -1;
connectState = ST_NOT_CONNECTED;
}
}
My understanding of synchronized methods is that they lock on this. So is the code equivalent to the following?
public synchronized void disconnect() {
if (isClosed())
return;
if (connectState == ST_CONNECTED) {
impl.disconnect ();
}
connectedAddress = null;
connectedPort = -1;
connectState = ST_NOT_CONNECTED;
}
Is there a reason why the language designers chose not to use a synchronized method here?
Yes, the two code snippets are equivalent.
We can only guess why whoever wrote this code chose the more verbose version. It could be someone's personal preference, or a historical artefact. For example, it might have previously been synchronized(someObject) or might have only covered part of the method, and whoever refactored the method didn't convert the synchronized section into a synchronized method.
Is there a reason why the language designers chose not to use a synchronized method here?
I don't know their minds, but in my mind, the first way is better. I really dislike the phrase "synchronized method", because methods are not what we need to protect with synchronization.
We need to protect data.
The entire point of synchronized blocks, is that often, in order to advance the state of the program, one thread must create a temporary, invalid state. With appropriate use of synchronized we can prevent any other thread from seeing the invalid state. It means synchronizing not just the block of code that is changing the state, but also, any other block of code that can examine the state.
I believe that the idea for synchronized methods came from a paper published in the 1970s describing monitors. https://en.wikipedia.org/wiki/Monitor_%28synchronization%29 A monitor basically is an object whose methods are all atomic. This was a useful abstraction when computer scientists were beginning to explore and formalize ways of thinking about parallel programming; but in a lot of practical applications, the "monitor" idea is too strict: It's hard to make the most efficient use of a multiprocessor system using only monitors.
I created a distributed lock class that I designed to be used like this:
myLock.lock();
doSomething();
myLock.unlock();
In my current implementation, lock() blocks until the lock is acquired. But I am running into some deadlock issues with this implementation. So I'd like to rewrite it to be asynchronous, but I have no idea how to do that in java.
Something like this would work I think:
myLock.lock(myCallbackFunction);
private void myCallbackFunction(boolean result){
if(result){
doSomething();
mylock.Unlock();
}
}
Is there a way to do this in java?
EDIT (More detail): The reasons why the synchronous implementation is deadlocking are complicated and not relevant. The distributed lock is acquiring mutual exclusion of a resource across a network with multiple systems. Really the only thing I'm looking for is how to write a method that accepts a callback function.
You can't do that in Java yet. What you can do is define a LockCallback interface:
interface LockCallback {
void run(boolean result, MyLock lock);
}
and have MyLock#lock take a LockCallback as a parameter. Then callers can call it as
myLock.lock(new LockCallback {
public void run(boolean result, MyLock lock) {
// ... do whatever needs to be done ...
lock.unlock();
});
Lambda syntax in Java 8 should make this a little less ugly looking.
Instead of writing your own and then abandoning the idea because you couldn't make it work, why not use a Semaphore, which is already there and is implemented correctly?
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?
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.
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.
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()
}
}
}
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.
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)
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).
This question already has answers here:
Synchronizing on String objects in Java
(20 answers)
Closed 5 years ago.
I want to do something like this in Java
public void giveMoney(String userId, int money) {
synchronized (userId) {
Profile p = fetchProfileFromDB(userId);
p.setMoney(p.getMoney() + userId);
saveProfileToDB(p);
}
}
But of course, synchronizing on a string is not correct. What's a correct way to do something like this?
If the set of user ids is limited, you can synchronize on an interned version of the String.
Either use String.intern() (which has a few drawbacks) or something like Guava Interners if you need a bit more control over the interning.
In principle, you can synchronize on any object in Java. It's not in itself "not correct" to synchronize on a String object; it depends on what exactly you're doing.
But if userId is a local variable in a method, then this is not going to work. Each thread that executes the method with have its own copy of the variable (presumably referring to a different String object for each thread); synchronizing between threads ofcourse only works when you make multiple threads synchronize on the same object.
You'd have to make the object you're synchronizing on a member variable of the object that contains the method in which you have the synchronized block. If multiple threads are then calling the method on the same object, you'll achieve mutual exclusivity.
class Something {
private Object lock = new Object();
public void someMethod() {
synchronized (lock) {
// ...
}
}
}
You could also use explicit locks from the java.util.concurrent.locks package, that can give you more control if you need that:
class Something {
private Lock lock = new ReentrantLock();
public void someMethod() {
lock.lock();
try {
// ...
} finally {
lock.unlock();
}
}
}
Especially if you want an exclusive lock for writing, but you don't want threads to have to wait for each other when reading, you might want to use a ReadWriteLock.
I guess there are a few options.
The easiest is that you could map a userId to a lock object in a threadsafe map. Others have mentioned interning but I don't think that's a viable option.
However, the more common option would be to synchronize on p (the Profile). This is appropriate if getProfile() is threadsafe, and by its name I would suspect it might be.
Theoretically speaking, since interned objects can be GC-ed, it's possible to synchronized on different objects (of the same value) at different times. Mutual exclusivity is still guaranteed, since it's not possible to synchronized on different objects at the same time.
However, if we synchronized on different objects, the happens-before relation is at doubt. We have to examine the implementation to find out. And since it involves GC, which Java Memory Model does not address, the reasoning can be quite difficult.
That's a theoretical objection; practically I don't think it'll cause any problem.
Still, there can be simple, direct, and theoretically correct solution to your problem. For example Simple Java name based locks?
You can use a proxy object for the string.
Object userIdMutex = new Object();
synchronized (userIdMutex) {
Profile p = getProfile(userId);
p.setMoney(p.getMoney() + p);
saveProfile(p);
}
Use this mutex whenever you access userId.
Based on your example, I assume you want to obtain a lock to a profile class, change it, and then release the lock. Synchronization is not exactly what you need in my opinion. You need a class that manages those records and lets you lock and unlock a record when changes need to be made to it, aka source control style.
Check this out: Lock class Java 5
What about this:
String userId = ...;
Object userIdLock = new Object();
synchronized (userIdLock) {
Profile p = getProfile(userId);
p.setMoney(p.getMoney() + p);
saveProfile(p);
}
It's simple and above all obvious.
I have a process A that contains a table in memory with a set of records (recordA, recordB, etc...)
Now, this process can launch many threads that affect the records, and sometimes we can have 2 threads trying to access the same record - this situation must be denied. Specifically if a record is LOCKED by one thread I want the other thread to abort (I do not want to BLOCK or WAIT).
Currently I do something like this:
synchronized(record)
{
performOperation(record);
}
But this is causing me problems ... because while Process1 is performing the operation, if Process2 comes in it blocks/waits on the synchronized statement and when Process1 is finished it performs the operation. Instead I want something like this:
if (record is locked)
return;
synchronized(record)
{
performOperation(record);
}
Any clues on how this can be accomplished?
Any help would be much appreciated.
Thanks,
One thing to note is that the instant you receive such information, it's stale. In other words, you could be told that no-one has the lock, but then when you try to acquire it, you block because another thread took out the lock between the check and you trying to acquire it.
Brian is right to point at Lock, but I think what you really want is its tryLock method:
Lock lock = new ReentrantLock();
......
if (lock.tryLock())
{
// Got the lock
try
{
// Process record
}
finally
{
// Make sure to unlock so that we don't cause a deadlock
lock.unlock();
}
}
else
{
// Someone else had the lock, abort
}
You can also call tryLock with an amount of time to wait - so you could try to acquire it for a tenth of a second, then abort if you can't get it (for example).
(I think it's a pity that the Java API doesn't - as far as I'm aware - provide the same functionality for the "built-in" locking, as the Monitor class does in .NET. Then again, there are plenty of other things I dislike in both platforms when it comes to threading - every object potentially having a monitor, for example!)
Take a look at the Lock objects introduced in the Java 5 concurrency packages.
e.g.
Lock lock = new ReentrantLock()
if (lock.tryLock()) {
try {
// do stuff using the lock...
}
finally {
lock.unlock();
}
}
...
The ReentrantLock object is essentially doing the same thing as the traditional synchronized mechanism, but with more functionality.
EDIT: As Jon has noted, the isLocked() method tells you at that instant, and thereafter that information is out of date. The tryLock() method will give more reliable operation (note you can use this with a timeout as well)
EDIT #2: Example now includes tryLock()/unlock() for clarity.
I found this, we can use Thread.holdsLock(Object obj) to check if an object is locked:
Returns true if and only if the current thread holds the monitor lock on the specified object.
Note that Thread.holdsLock() returns false if the lock is held by something and the calling thread isn't the thread that holds the lock.
Whilst the above approach using a Lock object is the best way to do it, if you have to be able to check for locking using a monitor, it can be done. However, it does come with a health warning as the technique isn't portable to non Oracle Java VMs and it may break in future VM versions as it isn't a supported public API.
Here is how to do it:
private static sun.misc.Unsafe getUnsafe() {
try {
Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
return (Unsafe) field.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void doSomething() {
Object record = new Object();
sun.misc.Unsafe unsafe = getUnsafe();
if (unsafe.tryMonitorEnter(record)) {
try {
// record is locked - perform operations on it
} finally {
unsafe.monitorExit(record);
}
} else {
// could not lock record
}
}
My advice would be to use this approach only if you cannot refactor your code to use java.util.concurrent Lock objects for this and if you are running on an Oracle VM.
While the Lock answers are very good, I thought I'd post an alternative using a different data structure. Essentially, your various threads want to know which records are locked and which aren't. One way to do this is to keep track of the locked records and make sure that data structure has the right atomic operations for adding records to the locked set.
I will use CopyOnWriteArrayList as an example because it's less "magic" for illustration. CopyOnWriteArraySet is a more appropriate structure. If you have lots and lots of records locked at the same time on average then there may be performance implications with these implementations. A properly synchronized HashSet would work too and locks are brief.
Basically, usage code would look like this:
CopyOnWriteArrayList<Record> lockedRecords = ....
...
if (!lockedRecords.addIfAbsent(record))
return; // didn't get the lock, record is already locked
try {
// Do the record stuff
}
finally {
lockedRecords.remove(record);
}
It keeps you from having to manage a lock per record and provides a single place should clearing all locks be necessary for some reason. On the other hand, if you ever have more than a handful of records then a real HashSet with synchronization may do better since the add/remove look-ups will be O(1) instead of linear.
Just a different way of looking at things. Just depends on what your actual threading requirements are. Personally, I would use a Collections.synchronizedSet( new HashSet() ) because it will be really fast... the only implication is that threads may yield when they otherwise wouldn't have.
Another workaround is (in case of you didnt have chance with the answers given here )is using timeouts. i.e. below one will return null after 1 second hanging:
ExecutorService executor = Executors.newSingleThreadExecutor();
//create a callable for the thread
Future<String> futureTask = executor.submit(new Callable<String>() {
#Override
public String call() throws Exception {
return myObject.getSomething();
}
});
try {
return futureTask.get(1000, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
//object is already locked check exception type
return null;
}
I needed to also find a solution to this, so searched the Java Concurrency API and came across StampedLock. The project is using Java 8.
I am working in a heavily-threaded asynchronous data service that communicates with a native library and contains long-living configuration objects, necessitating sometimes-complex concurrency logic; thankfully this turned out to be relatively simple with the StampedLock class.
StampedLock has a method called tryOptimisticRead which does not wait, it just returns the status in the form of a long-time time stamp, where zero (0) indicates an exclusive lock is held. I then do delay for up to a second but you could just use the function without any sort of delay.
Here's how I'm detecting whether or not there's an exclusive lock, this paradigm is used in multiple locations and includes error handling:
int delayCount = 0;
//Makes sure that if there is data being written to this field at
// this moment, wait until the operation is finished writing the
// updated data.
while (data1StampedLock.tryOptimisticRead() == 0)
{
try
{
delay(WRITE_LOCK_SHORT_DELAY);
delayCount += 1;
}
catch (InterruptedException e)
{
logError("Interrupted while waiting for the write lock to be
released!", e);
Thread.currentThread().interrupt();
//There may be an issue with the JVM if this occurs, treat
// it like we might crash and try to release the write lock.
data1StampedLock.tryUnlockWrite();
break;
}
if (delayCount * WRITE_LOCK_SHORT_DELAY > TimeUnit.SECONDS.toMillis(1))
{
logWarningWithAlert("Something is holding a write lock on" +
" the data for a very, very long time (>1s). This may" +
" indicate a problem that could cause cascading" +
" problems in the near future." +
" Also, the value for the data that is about to be" +
" retrieved could potentially be invalid.");
break;
}
}
long nonExclusiveLockStamp = data1StampedLock.readLock();
Data data1NonVolatile = data1;
data1StampedLock.unlockRead(nonExclusiveLockStamp);
return data1NonVolatile;
The read locks on a StampedLock are non-exclusive and are like reading from a thread-safe Map or HashTable, where it is multi-read/single-write.
Here is how I am using the exclusive lock to communicate to other threads that the instance data is being written to:
long d1LockStamp = data1StampedLock.writeLock();
this.data1 = data1;
data1StampedLock.unlockWrite(d1LockStamp);
So if you wanted to only check whether or not something is locked at any given moment, you need only something simple like the following statement to get the status:
boolean data1IsLocked = data1StampedLock.tryOptimisticRead() == 0;
Then check the value of that boolean.
There are, of course, the caveats and Here Be Dragons information mentioned in other answers (namely that the information is immediately stale), but if you really need to lock something and check that lock from another thread, this seemed to me to be the most reasonable, safe, and effective way that uses the java.util.concurrency package with no external dependencies.
Thanks for this, it helped me out solving a race condition. I changed it a little to wear both belt and suspenders.
So here is my suggestion for AN IMPROVEMENT of the accepted answer:
You can ensure that you get safe access to the tryLock() method by doing something like this:
Lock localLock = new ReentrantLock();
private void threadSafeCall() {
boolean isUnlocked = false;
synchronized(localLock) {
isUnlocked = localLock.tryLock();
}
if (isUnlocked) {
try {
rawCall();
}
finally {
localLock.unlock();
}
} else {
LOGGER.log(Level.INFO, "THANKS! - SAVED FROM DOUBLE CALL!");
}
}
This would avoid the situation where you might get two calling tryLock() at the almost same time, causing the return to be potentially doubt full. I'd like to now if I'm wrong, I might be over cautios here. But hey! My gig is stable now :-)..
Read more on my development issues at my Blog.