Fixing deadlocks in messy code - java

I'm modifying a bit of seriously complex code and I need to add my own synchronization on top of this.
However, the existing code has about a dozen, if not more, different locks, and my code needs to call some of its methods. I don't really know the order in which the locks are being obtained, nor can I really control it.
So, my question is, what would happen if I replaced all the different locks by a single lock?.Apart from sacrificing granularity, is there any other issue I should be aware of?
Thanks!

If you change all of the synchronized blocks (and methods), and all the other blocking structures, I think you should be fine -- worst case, your app degenerates to having serial execution. But if you only change some of them, you could get deadlock. Consider a scenario where two threads are each acquiring multiple locks:
Thread 1:
synchronized A
synchronized B
Thread 2:
synchronized B
synchronized C
There's no risk of deadlock here, but if you replace A and C (but not B) with the new, common lock, then you'll have:
Thread 1:
synchronized L
synchronized B
Thread 2:
synchronized B
synchronized L
... which is the classic deadlock case.
Consider another scenario, where the locks don't provide deadlock themselves, but instead deadlock a blocking class like a CountDownLatch:
Thread 1:
synchronized A
latch L.countDown()
Thread 2:
synchronized B
latch L.await()
In this case, changing both synchronized blocks to lock on a common lock won't cause deadlock between them, but will cause deadlock if thread 2 gets the lock first: it'll await the latch's countDown, which will never come because thread 1 is blocked at its synchronized entry point. This example applies to other blocking structures, too: semaphores, blocking queues, etc.

I don't think there is any substitute for properly analysing the code. The reason it is horrible is probably because everyone else who has had to modify it has done exactly the same as you and baulked at a proper analysis.
It should be fairly simple to write some logging code that should clarify the locking. Once you can unpick the layers and have a clear picture it should be comparatively simple to replace the whole lot with one modern lock such as a ReadWriteLock or similar.
You may find it useful to take this opportunity to add some test code to exercise your logging in a controlled fashion. A very useful addition to any piece of complex code.

Hard to say exactly what would happen without seeing the code.
You might run into a deadlock issue if while inside one of the locks, it tries to grab another lock. Also it could slow the application down while waiting to acquire a single lock vs multiple locks.

Related

Is it a bad practice to use pure lock() method in Java?

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.

Query about disadvantage of Reentrant locks over synchronized block

I am reading comparison between Reentrant locks and synchronization blocks in java. I am going through the various resources on internet. One disadvantage that I discovered using Reentrant locks over synchronization blocks is that in previous one, you have to explicitly use try finally block to call unlock method on the acquired lock in the finally block, as it might be possible that your critical section of code might throw exception and it can cause big trouble, if thread doesn't releases the lock, While in the latter one, JVM itself takes care of releasing the lock in case of exception.
I am not very much convinced with this disadvantage, because it's not a big deal to use try finally block.As we have been using it for long time for ex(stream closing etc). Can somebody tell me some other disadvantages of Re-entrant locks over synchronized blocks?
A ReentrantLock is a different tool for a different use-case. While you can use both for most synchronization issues (that's what they are made for), the come with different advantages and disadvantages.
Synchronized is at most simple: you write synchronized and that's it. With modern JVMs it is reasonable fast, but has the drawback that it puts all threads that try to enter a synchronized block on hold, whether they actually need to or not. If you use synchronized too often, this can dramatically reduce the speed of multi-threading, worst case down to a point where single-threaded execution would have been faster.
As threading issues only occur if someone is writing while someone else is reading/writing the same data section, programs often run into the problem, that they could theoretically run without synchronization, because most threads just read, but there is this one occasional write, which enforces the synchronized block. This is what the Locks were made for: you have a finer control over when you actually synchronize.
The basic ReentrantLock allows - beside a fair parameter in the constructor - that you can decide when you release the lock, and you can do it at multiple points, so when it suits you best. Other variations of it like the ReentrantReadWriteLock allow you to have many unsynchronized reads, except if there is a write. The downside is that this is solved in Java code, which makes it noticeably slower than the "native" synchronized block. That said: you should only use it, if you know that the optimization gain using this lock is bigger than the loss.
Under normal situations you can only tell the difference in speed if you actually monitor it, by running a profiler to check the speed before and afterwards in a sophisticated way.
synchronized is almost always faster for low or minimal contention, because it allows JVM to perform some optimizations such as biased locking, lock elision and others. Here are some more details how it works:
Let's assume some monitor is held by thread A, and thread B requests this monitor. In that case monitor will change its state to inflated. Saying short, it means that all threads trying to acquire this monitor, will be put to wait set at OS level, which is quite expensive.
Now, if thread A released monitor before thread B requested it, so-called rebias operation will be performed by cheap (on modern CPU) compare-and-swap operation.
Let's take a look at ReentrantLock now. Each thread calls lock() or lockInterruptibly() method cause locking attempt done via CAS operation.
Conclusion: in low contention cases, prefer synchronized. In high contention cases, prefer ReentrantLock. For all cases between, it is hard to say for sure, consider performing benchmarks to find out which solution is faster.

how using Lock interface gives more performance over using synchronise keyword in concurrent applications design?

I was going through "Java Concurrency CookBook". In that author mentioned using Lock interface gives more performance over using synchronized keyword.Can any one tell how? Using the terms like stack-frame, ornumber of method calls.
Don't mind, please help me get rid of java concurrency concepts.
The raison d'etre for Lock and friends isn't that it is inherently faster than synchronized(), it is that it can be used in different ways that don't necessarily correspond to the lexical block structure, and also that it can offer more facilities such as read-write locks, counting semaphores, etc.
Whether a specific Lock implementation is actually faster than synchronized is a moot point and implementation-dependent. There is certainly no such claim in the Javadoc. Doug Leas's book[1] where it all started doesn't make any claim that I can see quickly stronger than 'often with better performance'.
[1]: Lea, Concurrent Programming in Java, 2nd edition, Addison Wesley 2000.
1 Synchronisation is the only culprit that leads to the problem of deadlock unlike lock which is free of deadlock issue.
2 In synchronisation , we don’t know after how much time a thread will get a chance after a previous thread has released the lock. This can lead to problem of starvation whereas incase of lock we have its implementing class reentrant lock which has one of its constructor which lets you pass fairness property as one of its argument that leta longest waiting thread get the chance to acquire the lock.
3 In synchronisation, if a thread is waiting for another thread, then the waiting thread won’t do any other activity which doesn’t require lock access but with lock interface there is a trylock() method with which you can try for access the lock and if you don’t get the lock you can perform other alternate tasks. This helps to improve the performance of the application .
4 There is no api to check how many threads are waiting for a particular lock whereas this is possible with lock interface implementation class ReentrantLock methods.
5 One can get better control of locks using lock interface with holdCount() method which is not found with synchronization.

What are the "Conventional Techniques" to avoid deadlock?

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.

Disadvantage of synchronized methods in Java

What are the disadvantages of making a large Java non-static method synchronized? Large method in the sense it will take 1 to 2 mins to complete the execution.
If you synchronize the method and try to call it twice at the same time, one thread will have to wait two minutes.
This is not really a question of "disadvantages". Synchronization is either necessary or not, depending on what the method does.
If it is critical that the code runs only once at the same time, then you need synchronization.
If you want to run the code only once at the same time to preserve system resources, you may want to consider a counting Semaphore, which gives more flexibility (such as being able to configure the number of concurrent executions).
Another interesting aspect is that synchronization can only really be used to control access to resources within the same JVM. If you have more than one JVM and need to synchronize access to a shared file system or database, the synchronized keyword is not at all sufficient. You will need to get an external (global) lock for that.
If the method takes on the order of minutes to execute, then it may not need to be synchronized at such a coarse level, and it may be possible to use a more fine-grained system, perhaps by locking only the portion of a data structure that the method is operating on at the moment. Certainly, you should try to make sure that your critical section isn't really 2 minutes long - any method that takes that long to execute (regardless of the presence of other threads or locks) should be carefully studied as a candidate for parallelization. For a computation this time-consuming, you could be acquiring and releasing hundreds of locks and still have it be negligible. (Or, to put it another way, even if you need to introduce a lot of locks to parallelize this code, the overhead probably won't be significant.)
Since your method takes a huge amount of time to run, the relatively tiny amount of time it takes to acquire the synchronized lock should not be important.
A bigger problem could appear if your program is multithreaded (which I'm assuming it is, since you're making the method synchronized), and more than one thread needs to access that method, it could become a bottleneck. To prevent this, you might be able to rewrite the method so that it does not require synchronization, or use a synchronized block to reduce the size of the protected code (in general, the smaller the amount of code that is protected by the synchronize keyword, the better).
You can also look at the java.util.concurrent classes, as you may find a better solution there as well.
If the object is shared by multiple threads, if one thread tries to call the synchronized method on the object while another's call is in progress, it will be blocked for 1 to 2 minutes. In the worst case, you could end up with a bottleneck where the throughput of your system is dominated by executing these computations one at a time.
Whether this is a problem or not depends on the details of your application, but you probably should look at more fine-grained synchronization ... if that is practical.
In simple two lines Disadvantage of synchronized methods in Java :
Increase the waiting time of the thread
Create performance problem
First drawback is that threads that are blocked waiting to execute synchronize code can't be interrupted.Once they're blocked their stuck there, until they get the lock for the object the code is synchronizing on.
Second drawback is that the synchronized block must be within the same method in other words we can't start a synchronized block in one method and end the syncronized block in another for obvious reasons.
The third drawback is that we can't test to see if an object's intrinsic lock is available or find out any other information about the lock also if the lock isn't available we can't timeout after we waited lock for a while. When we reach the beginning of a synchronized block we can either get the lock and continue executing or block at that line of code until we get the lock.
The fourth drawback is that if multiple threads are awaiting to get lock, it's not first come first served. There isn't set order in which the JVM will choose the next thread that gets the lock, so the first thread that blocked could be the last thread to get the lock and vice Versa.
so instead of using synchronization we can prevent thread interference using classes that implement the java.util.concurrent locks.lock interface.
In simple two lines Disadvantage of synchronized methods in Java :
1. Increase the waiting time of the thread
2. Create a performance problem

Categories