Please skip to the TLTR if you do not want to read the whole story but the question:)
I need to fix a bug in our system and I have found the bug but could not find an optimal solution for this problem.
As an illustration, what it is aimed to be done is; when there are three files to be closed and for each file, a different thread (3 threads in this example) is created and should get the id of the file and by using file's id, it should close the file.
However, the person, who programs this, did not think something genuinely. At the moment, three threads are created for three different files and they access to the method, which distributes the ids, at the same time and the method gives the id of the first file (normally, first id to first thread, second id to second thread and third id to the third thread should be given) to three threads and these three threads try to close the same file (which causes the bug).
I cannot change this structure and it should be remain as it is.
TLTR
What I try to achieve is; how can I prevent several threads from entering the same method at the same time?
I tried synchronized (and lock) strategies for this but they did not help me in this situation, because each thread has its own lock (there are several objects created).
Create a singleton.
public static final Object globalLock = new Object();
Then in your methods where you need to protect.
synchronized(globalLock){
//get your file ids.
}
Couple of ways for doing this, here are some:
Make method synchronized
public class MyClass{
public void synchronized mySynchronizedMethod(); // only single thread will be allowed to invoke this method on the SAME INSTANCE OF MyClass
public void notSynchronizedMethod();
}
Use synchronized block:
MyClass obj=new MyClass();
synchronized(obj){
// only single thread is allowed to enter that block WITH obj INSTANCE.
obj.notSynchronizedMethod():
}
Synchronize on class
MyClass obj=new MyClass();
synchronized(MyClass.class){
//single thread is allowed for this block in a scope of WHOLE CLASS LOADER so in most cases you can say it is "globally" synchronized
}
Use Semaphore
Semaphore sem=new Sempahore(1);
sem.aquire(); // Thread will aquire permit, another thread will wait
//this will be synchronized block
sem.release(); allows another thread to aquire permit
Related
I have a java multithreading issue. I have 2 threads accessing a methodA() which has a for loop inside and in the loop calls a methodB(). The method A should be locked using a thread-name lock and the method B should be locked on the object id that the method B operates on. Check the below code.
Currrent code
private static final ConcurrentHashMap<Object, Object> LOCKS = new ConcurrentHashMap<Object, Object>();
private void methodA(){
LOCKS.putIfAbsent(Thread.currentThread().getName(), new Object()))
synchronized (LOCKS.putIfAbsent(Thread.currentThread().getName(), new Object())) {
for(loop through all objects) {
methodB(Object1);
}
}
}
private void methodB(Object1 object1) {
LOCKS.putIfAbsent(object1.getObjectId(), new Object()))
synchronized(LOCKS.putIfAbsent(object1.getObjectId(), new Object())){
//<Work on object1>
}
}
I had done the above code to ensure that 2 different threads should be able to paralleley access methodA(), but should not work on same Object1 at a time in methodB() (which is invoked by methodA()).
ie; Though I want Thread A and Thread B to access methodA() at the same time, which in turn will loop through all objects in 'for' loop and will operate on each by calling methodB(), I dont want thread A and B to act on the SAME object instance at a time. Hence the above code to lock methodB() based on object instance ID.
The improvement needed.
In the above code if Thread A and Thread B comes to methodB() and finds that they both want to work over the same object 'obj1', right now with the above code either Thread A will wait or Thread B will wait for the other one to finish depending on who reached and locked methodB() first.
But imagine a case, where Thread A getting the lock first and executing methodB() takes 9 hours to finish processing 'obj1'. Thread B in this case will need to wait for the entire 9 hours before getting a chance to execute methodB() and thereby processing 'obj1'.
I don't want this to happen. Thread B, once it finds that methodB() is locked in the name of 'obj1' by Thread A should move on (and come back to obj1 later) to try locking and processing other objects. ie; it should try processing other objects in the 'for' loop like obj1, obj2 etc in the list of objects.
Any inputs to solve this 'lock without wait' problem will be appreciated.
Many thanks in advance for any help.
Some clarifications to improve the answers.
Both methodA() and methodB() is in same class. The methodB() is not in the Object class.
Actually Thread A and Thread B are timer threads that calls many methods including A and B. Hence the thread level lock (because thread gets called every 15 mins or so and there is a chance that the first execution of methodA() wont be completed before a second call to it).
methodB(Obj1) always takes a Object1 param and must be locked on it. The reason is, in this class there are be other methods say methodC(Obj1) and methodD(Obj1) that also takes in an Object1 param. These methods should not get executed at the same time for same instance of Object1. Hence the lock on Object1 param needed.
The Thread B finding that methodB(Obj1 obj) is already locked by Thread A() on obj1 needs to somehow call methodB() again but with a different object, say obj2. It should come back to obj1 once it finishes with the others.
The best thing you can do is to keep things simple.
The method A should be locked using a thread-name lock
Only locking shared objects makes sense. Lock a thread local lock is pointless.
synchronized(LOCKS.putIfAbsent(object1.getObjectId(), new Object()))
That will return null and throw a NullPointerException the first time it is run.
I would replace the code with
private void methodA(){
List<Object1> objects = new ArrayList<>(this.objectList);
while(true) {
for(Iterator<Object1> iter = objects.iterator() : objects)
if(object1.methodB())
iter.remove();
if(objects.isEmpty()) break;
Thread.sleep(WAIT_TIME_BEFORE_TRYING_AGAIN);
}
}
// in class for Object1
final Lock lock = new ReentrantLock();
public boolean methodB() {
if (!lock.tryLock())
return false;
try {
// work on this
return true;
} finally {
lock.unlock();
}
}
Depending on how you want to handle object which cannot be locked, you could add them to a background ExecutorService. You could have methodA repeatedly call all the remaining objects for which this fails.
Ideally you would find a way to minimise the time locked or even remove the need for a lock entirely. e.g. Classes like AtomicReference and CopyOnWriteArrayList are thread safe and lockless.
I am not a Java guy, but in my opinion you will not achieve this with synchronized. I believe you will need to do your own locking.
If you create a java.util.concurrent.locks.ReentrantLock you can use tryLock to enter the lock if it is not yet locked. methodA needs to know which methodB call was successful or which was canceled because the lock was not possible. So you could do the lock handling in methodA, giving you full control there. Or you could do the locking in methodB, but then you need some return value or exception handling to signal back to methodA if methodB did its work or if it did not get the lock.
Of course you will also need to keep a list in methodA of the objects you already went through or of the objects you still need to work on.
Does it matter if one thread pass occasionally 'misses' an object on a pass-through? If not:
Store all the objects in a lockable queue-style container. Have threads A, B etc. pop one out, call methods on it and then push it back in. It is then not possible for the threads to operate on the same object at the same time. The only lock is then on the container push/pop and no thread needs to block for any extended time.
..or something like that. I always try to avoid complex locking schemes - they always seem to screw up :(
I suggest a different approach. Instead of directly invoking the method, put a command object in a queue and have a thread (or an executor) process the commands.
When a command appears in the queue, try to get the lock. If that doesn't work, add the command to the end of the queue. This will make sure the command is tried again eventually.
Drawback: A command could be postponed indefinitely if some thread happens to have lock on it every time it's tried for execution.
The solution here would be to make sure you only lock what you need. That way, when you see "oh, this is locked", you know that someone is already working on the task and you can simply forget about the command (-> don't do work twice).
What is the difference or impact between using the synchronized block as in method1 and method2?
class A
{
private Object lock = new Object();
...
...
private void method1()
{
synchronized(A.class)
{
.....
}
}
private void method2()
{
synchronized(lock)
{
....
}
}
}
In first method all threads that use ANY instance of the class A will be syncronised.
In second method all threads that use THIS instance of the class A will be syncronised.
Since A.class is avaliable to others, it is public in effect. If something else uses it to synchronize access to some section of code then your section of code could be blocked. This might be good or bad; but you don't have control over it.
Using an internal object allows you to decare it as private so that you have complete control over where and when it is used. I prefer to use an internal object that I have control.
Lock is an ordinary field. So there is one of it for each instance of 'A'. A.class is global to the whole JVM. So the two blocks have completely different semantics. The version with 'lock' says, 'only one thread can be in this block for this instance of A'. The version with A.class says 'only one thread can be in this block for any instance of A.
In the first case, you synchronize on a public object (A.class), and so other parts of the application might cause problems because they also synchronize on A.class.
In the second case, you synchronize on a private lock object, and are thus sure that nobody else uses the the lock to synchronize access to something else.
Moreover, as indicated in other answers, all the instances of the class will be synchronized on the same lock with the first solution, whereas each instance will have its own lock with the second solution.
The second solution is thus much preferred (although the lock object should be final).
The parameter of synchronized block is needed to be able to create several "named" blocks. So using special lock object is probably more flexible: you can create lock1 and lock2 in future.
Yet another aspect is waiting and notification. You can say lock.wait() and then lock.notfify() from another thread. In this case you can also use both ways (special lock object or A.class as a lock).
Can someone please explain the difference between these two examples in the context of object locking:
public void method1(){
synchronized(this){
....
}
}
And
StringBuffer aStringBufferObject = new StringBuffer("A");
public void method2(){
synchronized(aStringBufferObject){
....
}
}
I know the first example will obtain a lock on the this instance and the second will obtain a lock of the aStringBufferObject instance. But i dont really understand what the effect or the difference of the two is.
For example, in the second example, will threads still be able to execute the code inside the synchronized block because the lock is not related to the 'this' instance?
I know that synchronizing a method or a block of code prevents multiple threads to access that block/method at the same time but what is the purpose of specifying the object to lock on and what is the difference in the way the object is specified as in the above examples?
What is the purpose of specifying the object to lock on?
Often, it is easier to synchronize on this or on the Class instance (for static methods). But, there are cases where you will need to synchronize on a specific object instead of the implicit lock (this). Such cases include:
You want to synchronize access to primitives without using this. You can only synchronize on Objects as each Object is associated with an implicit monitor in Java. Primitives do not have such implicit monitors, and therefore you need to use a lock object. Using the wrapper classes are a poor and incorrect choice, especially if you end up modifying the lock object in the guarded block.
You want to synchronize on an object that actually protects the critical section, when synchronizing on this would not offer a guarantee of thread safety. For instance, if you are synchronizing access to a ArrayList instance shared across instances of class A, then synchronizing on an instance of A is useless. A thread might create a new instance of A and gain access to the list, while another thread is modifying it. If you use a different lock that all threads must contend for then you can protect the list; this lock could be the one associated with A.class, but it could be any object that will offer the same guarantees.
You want to perform lock splitting to ensure that different guarded blocks are protected by different locks instead of the same lock. In other words, if it is thread-safe to allow different threads to acquire different locks to access different critical sections, then you can have a different lock for every critical section.
The following is an example of split lock usage:
private Object method1Lock = new Object();
private Object method2Lock = new Object();
public void method1(){
synchronized(method1Lock){
....
}
}
public void method2(){
synchronized(method2Lock){
....
}
}
You would use split locks when you can ensure that the concurrent execution of method1 and method2 do not violate the class invariants. This way, you can improve performance across threads that need access to the same object, but will be invoking different methods.
On your other question,
For example, in the second example, will threads still be able to execute the code inside the synchronized block because the lock is not related to the 'this' instance?
In the second example, any thread entering the guarded region must acquire the lock associated with aStringBufferObject. If a different thread is holding that lock, then the current thread will not proceed further. When you specify this, then the thread must acquire the lock associated with the current object. In both cases, a thread must acquire a lock; the examples are only different in the object that is being used as a lock.
Synchronizing on an object means that other blocks which synchronize on the same object will have to wait. For example:
public void methodA() {
synchronized(obj) {
//Do one job
}
}
public void methodB() {
synchronized(obj) {
//Do another job
}
}
If you call methodA() in one thread and then call methodB() in another thread, methodB() won't finish before methodA() finishes.
The synchronized block is a monitor, which leave out of details to lock and unlock a mutex. Because every object in Java has an internal lock(refer to source code of Object class), when use synchronized statement, the JVM will help you synchronize the critical section. You can also synchronize block yourself use ReentrantLock in package java.util.concurrent.locks.
i have a variable on my "SharedPreferences", that is accesed by two different threads, one in a service, and one in a activity.
There is a easy way to protect this variable to be accesed by two threads at once?
i need to protect this code:
configEditor.putString("mylatitude", ""+currentLocation.getLatitude());
configEditor.putString("mylongitude", ""+currentLocation.getLongitude());
configEditor.commit();
i tryed with this but doesn't works:
Object LOCK = new Object();
synchronized (LOCK){
configEditor.putString("mylatitude", ""+currentLocation.getLatitude());
configEditor.putString("mylongitude", ""+currentLocation.getLongitude());
configEditor.commit();
}
thanks
Object LOCK = new Object();
synchronized (LOCK) {
// lines of Java code that has to be thread safe
}
EDIT: edit the code to be exactly for the situation when the code is modifying several variables and it has to be thread-safe. For a single variable (as is in the title of the question) lock the variable itself, you don't need a separate lock for it.
I'm not sure, but I believe using a Handler may be what you need.
Take a look at this article, which explains when and how to use them. It also provides some code samples which may be helpful.
Try something like this:
public class MyClass {
private final Object lock = new Object();
public myMethod() {
...
synchronized (lock) {
// At most one thread is executing this
// at the same time for this instance
}
...
}
}
The important thing is that the lock object should be an instance (and not local) variable, so that every thread uses the same lock for that particular instance of MyClass. Most of the time you want it to be final so that there is no posibility of changing it by mistake.
If you make the lock static, then at most one thread will be executing the synchronized section, no matter in which instance of MyClass.
EDIT:
For your particular case, you can adapt the following idea:
public class Service {
public void doSomethingWithConfigEditor() {
ConfigEditor configEditor = // get configEditor
synchronized (configEditor) {
// something with configEditor
}
}
}
public class Activity {
public void doAnotherThingWithConfigEditor() {
ConfigEditor configEditor = // get configEditor
synchronized (configEditor) {
// another thing with configEditor
}
}
}
By synchronizing on configEditor, you guarantee that those two blocks of code never execute in parallel on the same instance of ConfigEditor.
This is typically done using critical sections aka mutexes. Before accessing the variable, your thread should aquire a lock on the mutex. While the mutex is locked, any attempt to aquire another lock will wait until the previous lock is released. This way, threads will wait for each other when accessing the variable.
You need to put the synchronized block in both locations that access the variable which you are trying to protect. Protecting it only one of the locations doesn't help.
Are you sure this is in two different threads? Your service code will only be running in a different thread if you are executing due to someone calling through to your IBinder interface from another process (or another thread in your own process).
I am pretty new to thread-safe programming, and was wondering if I have something like below, would this be safe from deadlock once compiled and run?
public class Foo
{
protected CustomClass[] _mySynchedData = new CustomClass[10];
public void processData()
{
synchronized(_mySynchedData) {
// ...do stuff with synched variable here
}
}
}
public class Bar extends Foo
{
#Override
public void processData()
{
synchronized(_mySynchedData) {
// perform extended functionality on synched variable here
// ...then continue onto parent functionality while keeping synched
super.processData();
}
}
}
Bar testObj = new Bar();
// Deadlock?
testObj.processData();
Your code only display a single thread.
With only one thread, there's no way you can get any deadlock.
Added:
Java language supports what they officially call reentrant synchronization.
It basically means that a single thread can reacquire a lock it already owns.
Your question is what happens when you synchronize two times on the same object.
The answer is: Java will check first which thread owns the monitor (that's the internal data structure on which synchronized operates). Since the owner thread is the same as the current thread, Java will continue.
Deadlocks can only happen if you have two monitors and you try to lock them in different orders in different threads.
The lock taken by the Java synchronized keyword supports nesting, so you don't risk a deadlock by synchronizing on the same object multiple times in the same thread.
RichN is correct in that your code only contains a single thread and hence deadlock is impossible. Also note that for a deadlock to occur you need to have multiple threads acquiring multiple locks (albeit in a different order) for a deadlock to occur.
Your code currently only references one lock: The one associated with _mySynchedData. The fact that you attempt to lock it twice does not matter as locks in Java are reentrant.