Implementing a global lock in Java - java

I have a relatively simple (perhaps stupid) question regarding synchronisation in Java.
I have synchronisation blocks that acquire locks on various objects throughout my code. In some scenarios, I want to acquire a global lock that subsumes every other synchronisation statement in my code.
Is there a fancy way to do this in Java without re-writing all the current synchronisation code?
For example,
Thread t1
synchronized (o1)
{
synchronized (o2)
{
// ...
}
}
Thread t2
synchronized (global_lock)
{
// ...
}
When thread t2 is inside the synchronised block, thread t1 should not be allowed to acquire the locks on o1 and o2.
Many thanks
if

It's not possible;
It's a really bad idea ( sorry ).
It's deadlock-prone, since it forces you to have a pre-determined locking order for all locks, no matter where they are.
Usually it's a good idea, if you need to acquire two locks, to always have a predetermined order:
synchronized(LOCK1) {
synchronized(LOCK2) {
}
}
But a global lock would need some sort of protocol - a global aquisition order - for all the locks. And that may not be possible at all. Most locks guard specific, self-contained, critical sections. They would be unaware that someone would 'yank' them out and aquire them and therefore would not be written to handle this situation.
So it's not possible, and you should be happy it's not. Although it seems to be the easy way out, it would bring a lot of pain.

Leaving aside the sheer horror of what you are proposing, you may want to consider using Aspect Oriented Programming (AOP) to "weave" additional synchronization/locking into your code at run time. You should be able to do this without writing the source.
There are many AOP options, including AspectJ and Spring AOP, which may be suitable depending on your environment.

The only feasible way to do it would be actually parse/modify/save (automatically) all the code. I did something like this for a project recently and it worked pretty good. We can talk more if you are interested.

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.

Is there a fail-fast way of synchronization in Java?

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

Fixing deadlocks in messy code

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.

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.

When do we make a call to use between Synchronised method and Synchronised Block

Can any one please share their experience on
"When do we make a call to use between Synchronised method and Synchronised Block"
Any Performance Issues?
When do we make a call to use between Synchronised method and Synchronised Block.
If you want to lock for the duration of a method call AND you want to lock on this (or the current class, for a static method), then synchronized methods are the right solution.
If you are locking on something else (e.g. a private lock object or some internal data structure), then the synchronized block approach is better.
Similarly, if only some of the code in a procedure call needs to be done holding a lock, it is better to use a synchronized block and put just that code in the block.
Any Performance Issues?
None, apart from the general principal that it is a bad idea to hold a lock longer than you need to. (The longer a lock is held, the more likely it is that other threads will need to wait.)
I'm not sure what you mean by "synchronized statement". You use the synchronized keyword to either denote that a method is synchronized or (as you mention) a block of code within it.
I typically favour keeping methods small and manageable and therefore labelling the entire method as synchronized (when required). This has the advantage that it is immediately evident to a user of the class as to which methods represent critical sections. It also allows you as a programmer to more easily determine whether a class is thread-safe, namely: Are all public methods that access mutable data labelled as synchronized?
There is no performance difference between the approaches as both require obtaining a lock.
Always try to use Synchronized block if possible, for any case its not possible then go for Synchronized method. Will be a lot of performance improvements depend on the no. of lines in the Synchronized method. As no. of lines increases,performance will degrade.
I tend to use synchronized methods when it is the public interface that requires synchronization (c.f. synchronized collections) and synchronized blocks for class internal synchronization, such as access to a shared resource which needs to be thread safe.
There is also a readability issue. I find method level synchronization to be neater and more obvious as the code is not cluttered with lock management.
As for performance, I'm not aware of any particular difference in the behaviour of either approach. I think it is more important to avoid excessive synchronization, so a method which only needs access to the shared resource 1 in 10 calls should use block level rather than method level synchronization.
My approach to any given scenario is usually based on a mix of these factors, modified by previous experience.
In terms of overall performance, there is no difference between having a synchronized block or method. The issue is really in terms of coding practices. Synchronizing a method seems like an easy thing to do however, when working with multiple people on a project, it becomes possible for someone to alter a simple light method that someone else synchronized into a heavy operation one. In fact, one really good example (from personal experience) of where you can get into trouble is when you are using a dependency injection framework and you have methods in a service object that interact with data access objects (daos) that are synchronized. The expectation is that the daos perform quickly so the locks are only held briefly. Someone else comes along and either alters the daos or creates and injects new ones that are much slower and suddenly things start to really slow down because the service object has synchronized interaction with it.
I don't think synchronized blocks can get around that issue that I described above however, at least with synchronized blocks, they are harder to miss than a declaration in the method.

Categories