Let's say I have a code snippet like this
synchronized(obj) {
do something;
}
If obj was already locked by some other thread, this code will wait until obj released and after that it will try to get the lock.
But I want to know if there is any way to jump over the code block if the lock can not be gained immediately?
Or put it another way, is there a way to detect whether or not an object is already locked ?
UPDATE:
Thanks for mentioning the Lock interface, but that require programs to obey the same contract, i.e, they all refer to a Lock object instead of the synchronized keyword.
I wonder if there is a built-in way of checking the locking status ?
Thanks.
Is there a fail-fast way of synchronization in Java?
I think it is a poor choice of terminology to use "fail-fast" to describe what you are trying to do here. Fail-fast implies that not being to acquire a lock instantly is a failure or application error; c.f. fail-fast iterators which throw an unchecked CCME. That's not the semantic model offered by locks in general, or here in particular. A better term would be "non-blocking"
Also, it is not clear that silently skipping a block of code because you can't acquire a lock is useful behavior. In most cases, the application needs to know that the "skip" path has been taken.
These points aside, you can't do it using primitive object locks.
(OK, on some JVMs you might be able to use sun.misc.Unsafe to do this, but that's a really bad idea. You are likely to find that your compiler, class loader or security sandbox stops you from using the Unsafe API ... as it should. Besides, this API is not called "unsafe" for nothing!)
The java.util.concurrent.locks.Lock API has a method that allows you to attempt to gain a lock without blocking. Specifically, the tryLock() method attempts to acquire the lock and immediately returns false if the lock is in use.
There are other higher level concurrency classes that you could use as ersatz locks; e.g. Semaphore.
Or put it another way, is there a way to detect whether or not an object is already locked ?
Actually, that is a bit different ... and not entirely useful either. Sure, you could (hypothetically) test if a lock is being held. (Indeed some Lock classes explicitly support this.) But that doesn't mean that you'd be guaranteed to be able to acquire the lock without blocking. If you make that (incorrect) assumption, you've introduced a Heisenbug into your code.
I wonder if there is a built-in way of checking the locking status ?
[Assuming that you are referring to primitive locks ... ]
No there isn't. At least, not within the running application itself. (A debug agent can do this, but it is not practical for an application to talk to its JVM's debug agent.)
If you want / need to do this kind of thing, you've got no real options that don't involve changing your application's locking mechanism. That's the way it is.
you can do it using java.util.concurrent.Semaphore it will allow you more control
Related
According to documentation:
void lock()
Acquires the lock.
If the lock is not available then the current thread becomes disabled for thread scheduling purposes and lies dormant until the lock has been acquired.
I'm using timed tryLock nearly everywhere, handling all what is expected - if timout ends, if it is interrupted, and so on.
But today, I've thought: is it bad/unsafe/dangerous to use pure lock()?
Examples showing it looking so cute and elegant - just lock and unlock in finally. I've googled, but haven't found answer about it being a bad practice.
It depends on how you use it inside of your code. If you just use it, only for lock and unlock, then you don't use any of the features it provides. So, you can merely fallback to intrinsic locks using the keyword synchronized. However, if you use timed lock and interruptible locking facilities, then it may be reasonable given your specific usecase warrants it. Intrinsic locks still have significant advantages over explicit locks. The notation is familiar and compact. Oftentimes, developers forget to call unlock on explicit locks, making it much more prone to errors.
Moreover, if you use condition objects you can still use either of them. If you have only one condition for the lock object, I would rather use intrinsic locks. The explicit locks become handy when you need to have multiple conditions for a given lock and need to use it without any interference from other conditions on the same lock.
In conclusion, it all depends on how you use it and whether your usecase warrants it.
There's nothing to say if its bad or good. If you need to handle critical blocks, you need to lock it.
I am coding on a multithreaded environment and I see threads are stuck on HashMap.put:
34 Threads
java.util.HashMap.put(HashMap.java:374)
com.aaa.bbb.MyClass.getDefinitionMap().
Investigating the method that is the HashMap I see that the method is synchronized:
#Override
public synchronized Map<String,String> getDefinitionMap() {
//truncated some code here...
colDefMap = new HashMap<String,String>();
for (CD cd : (List<CD>)cm.getDef()) {
colDefMap.put(cd.getIdentifier(),cd);
}
return colDefMap;
}
So after switching to ConcurrentHashMap, removing the synchronized keyword from the method signature and restarting the application server - problem is resolved.
My question is why synchronized method is not sufficient in this scenario to protect the map from concurrent access?
You don't say how "stuck" this is, whether you actually have a deadlock or a bottleneck.
I would expect the posted code to be a bottleneck, where almost all your threads are trying to access the same object, waiting on acquiring the lock used by the synchronized method. It's likely that whatever cm.getDef does takes a while and only one thread at a time can make progress. So synchronizing does protect the data from concurrent access, just at the expense of throughput.
This fits the definition of "starvation" given in the Java concurrency tutorial:
Starvation describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress. This happens when shared resources are made unavailable for long periods by "greedy" threads. For example, suppose an object provides a synchronized method that often takes a long time to return. If one thread invokes this method frequently, other threads that also need frequent synchronized access to the same object will often be blocked.
Switching to ConcurrentHashMap is a good improvement, as you observed. ConcurrentHashMap avoids locking threads out of the entire map, and supports concurrent updates, see the API doc (my emphasis):
A hash table supporting full concurrency of retrievals and high expected concurrency for updates. This class obeys the same functional specification as Hashtable, and includes versions of methods corresponding to each method of Hashtable. However, even though all operations are thread-safe, retrieval operations do not entail locking, and there is not any support for locking the entire table in a way that prevents all access. This class is fully interoperable with Hashtable in programs that rely on its thread safety but not on its synchronization details.
You might consider caching whatever cm.getDef does so you don't have to call it every time, but the practicality of that will depend on your requirements, of course.
You were synchronizing on the getDefinitionMap method in the subclass, which is apparently not the only method (or class) that has access to cm.
The iterator on the class variable cm is the likely culprit:
for (CD cd : (List<CD>) cm.getDef())
{
colDefMap.put(cd.getIdentifier(), cd);
}
In the above code, the cm variable is likely being modified while you are iterating over it.
You could have used the following:
synchronized (cm)
{
for (CD cd : (List<CD>) cm.getDef())
{
colDefMap.put(cd.getIdentifier(), cd);
}
}
However, this would have still left modification of cm open to other threads, if modifications to cm were performed without similar synchronization.
As you discovered, it is much easier to use the thread-safe versions of the collections classes than to implement workarounds for non-thread-safe collections in a multi-threaded environment.
I think you may be wrong by thinking that you solve your problem. Removing the synchronized means that you unlock access to this method which can resolve your problem and brings others. I mean your HashMap is created in the scope of your function so its obviously not here that you should have a concurrency probleme (if what is put inside is not static or thread-Safe). Never the less here using concurrentHashMap has no effect.
I suggest you to try and see in a multi-thread test if your function do properly is job without the synchronized statement (without the concurrentMap).
In my opinion without knowing the rest of your code, this function may be accessing static or shared data that may be lock by a thread so the problem do not come from the function but an other object interacting with it at some point.
Are you modifying it anywhere else? Are you 100% sure it's not being put somewhere else? I suspect you are and what is likely is that the second put is causing an infinite loop. http://mailinator.blogspot.com/2009/06/beautiful-race-condition.html
Otherwise, if this is the only place you are modifying the HashMap, it should be fine.
This question is NOT about alternatives to Thread.suspend.
This is about the possibility to implement a bias lock with Thread.suspend, which (I believe) can't be implemented with Thread.interrupt or similar alternatives.
I know Thread.suspend is deprecated.
But I want to know the precise semantics of Thread.suspend.
If I call thread1.suspend(), am I guaranteed to be blocked until thread1 is fully stopped? If I call thread1.resume(), can this call be visible to other threads out of order?
More over, if I successfully suspend a thread, will this thread be suspended at a somewhat safe point? Will I see its intermediate state (because Java forbids out of thin air value even in not properly synchronized program, I don't believe this is allowed) or see something out of order (if suspend is an asynchronous request, then sure I will see that kind of thing)?
I want to know these because I want to implement some toy asymmetric lock within Java (like BiasedLock in HotSpot). Using Thread.suspend you can implement a Dekker like lock without store load barrier (and shift the burden to the rare path). My experimentation shows it works, but since a Thread.sleep is enough to wait for a remote context switch, I am not sure this is guaranteed behavior.
By the way, are there any other way to force (or detect) remote barrier? For example, I search the web and find others use FlushProcessWriteBuffers or change affinity to bind a thread to each core. Can these tricks done within Java?
EDIT
I came up with an idea. Maybe I can use GC and finalizer to implement the biased lock, at least if only two threads are there. Unfortunately the slow path may require explicit gc() call, which isn't really practical.
If GC is not precise, I maybe end up with a deadlock. If the GC is too smart and collect my object before I nullify the reference (maybe the compiler is allowed to reuse stack variables, but is the compiler allowed to do these kind of things for heap variables, ignoring acquire fence and load fence? ), I end up with corrupted data.
EDIT
It seems a so called "reachability fence" is needed to prevent the optimizer moveing an object's last reference upward. Unfortunately it's no where.
Its semantics consist entirely of what is specified in the Javadoc:
Suspends this thread.
First, the checkAccess method of this thread is called with no arguments. This may result in throwing a SecurityException (in the current thread).
If the thread is alive, it is suspended and makes no further progress unless and until it is resumed.
But as you're not going to use it, because it's deprecated, this is all irrelevant.
I have a Results object which is written to by several threads concurrently. However, each thread has a specific purpose and owns certain fields, so that no data is actually modified by more than one thread. The consumer of this data will not try to read it until all of the writer threads are done writing it. Because I know this to be true, there is no synchronization on the data writes and reads.
There is a RunningState object associated with this Results object which serves to coordinate this work. All of its methods are synchronized. When a thread is done with its work on this Results object, it calls done() on the RunningState object, which does the following: decrements a counter, checks if the counter has gone to 0 (indicating that all writers are done), and if so, puts this object on a concurrent queue. That queue is consumed by a ResultsStore which reads all of the fields and stores data in the database. Before reading any data, the ResultsStore calls RunningState.finalizeResult(), which is an empty method whose sole purpose is to synchronize on the RunningState object, to ensure that writes from all of the threads are visible to the reader.
Here are my concerns:
1) I believe that this will work correctly, but I feel like I'm violating good design principles to not synchronize on the data modifications to an object that is shared by multiple threads. However, if I were to add synchronization and/or split things up so each thread only saw the data it was responsible for, it would complicate the code. Anyone who modifies this area had better understand what's going on in any case or they're likely to break something, so from a maintenance standpoint I think the simpler code with good comments explaining how it works is a better way to go.
2) The fact that I need to call this do-nothing method seems like an indication of wrong design. Is it?
Opinions appreciated.
This seems mostly right, if a bit fragile (if you change the thread-local nature of one field, for instance, you may forget to synchronize it and end up with hard-to-trace data races).
The big area of concern is in memory visibility; I don't think you've established it. The empty finalizeResult() method may be synchronized, but if the writer threads didn't also synchronize on whatever it synchronizes on (presumably this?), there's no happens-before relationship. Remember, synchronization isn't absolute -- you synchronize relative to other threads that are also synchronized on the same object. Your do-nothing method will indeed do nothing, not even ensure any memory barrier.
You somehow need to establish a happens-before relationship between each thread doing its writes, and the thread that eventually reads. One way to do this without synchronization is via a volatile variable, or an AtomicInteger (or other atomic classes).
For instance, each writer thread can invoke counter.incrementAndGet(1) on the object, and the reading thread can then check that counter.get() == THE_CORRECT_VALUE. There's a happens-before relationship between a volatile/atomic field being written and it being read, which gives you the needed visibility.
Your design is sound, but it can be improved if you are using a true concurrent queue since a concurrent queue from the java.util.concurrent package already guarantees a happens before relationship between the thread putting an item into the queue, and the thread taking an item out, so this precludes needing to call finalizeResult() in the taking thread (so no need for that "do nothing" method call).
From java.util.concurrent package description:
The methods of all classes in java.util.concurrent and its subpackages
extend these guarantees to higher-level synchronization. In
particular:
Actions in a thread prior to placing an object into any
concurrent collection happen-before actions subsequent to the access
or removal of that element from the collection in another thread.
The comments in another answer concerning using an AtomicInteger instead of synchronization are also wise (as using an AtomicInteger to do your thread counting will likely perform better than synchronization), just make sure to get the value of the count after the atomic decrement (e.g. decrementAndGet()) when comparing to 0 in order to avoid adding to the queue twice.
What you've described is indeed safe, but it also sounds, frankly, brittle and (as you note) maintenance could become an issue. Without sample code, it's really hard to tell what's really easiest to understand, so an already subjective question becomes frankly unanswerable. Could you ask a coworker for a code review? (Particularly one that's likely to have to deal with this pattern.) I'm going to trust you that this is indeed the simplest approach, but doing something like wrapping synchronized blocks around writes would increase safety now and in the future. That said, you obviously know your code better than I do.
I saw the below statement in Java Specifications.
Programs where threads hold (directly
or indirectly) locks on multiple
objects should use conventional
techniques for deadlock avoidance,
creating higher-level locking
primitives that don't deadlock, if
necessary.
So, What are the "Conventional Techniques" to follow to avoid deadlock? I'm not pretty clear with this (not understood properly, explanation needed).
The most common technique is to acquire resources (locks) in some consistent well-defined order.
The following article by Brian Goetz might be helpful: http://www.javaworld.com/javaworld/jw-10-2001/jw-1012-deadlock.html
It's pretty old, but explains the issues well.
As a somewhat absract suggestion, an answer to this might be "Have a plan for handling locks and stick to it".
The danger of locking is where, in short, one thread holds lock A and is trying to get lock B, while another thread holds lock B and is trying to get lock A. As noted by another answer, the clasic way to avoid this is to get locks in a consistent order. However, a good discipline is to minimize the amount of work that your code does with a lock held. Any code that calls another function with a lock held is a potential problem: what if that other function tries to get another lock? What if someone else later modifies that function to get a lock? Try to form a clear pattern of what functions can be called with locks held, and what cannot, and make sure the comments in your code make this all clear.
Don't do locking! Seriously. We get immense performance (100k's of transactions at sub-millisecond latency) at my work by keeping all our business logic single threaded.