Java synchronize on object - java

How to synchronize two different methods from the same class in order to lock on the same object? Here is an example:
public class MyClass extends Thread implements Observer{
public List<AnotherClass> myList = null;
public MyClass(List<AnotherClass> myList){
this.myList = myList;
}
public void run(){
while(true){
//Do some stuff
myList.add(NotImportantElement);
}
}
public void doJob{
for(int i=0; i<myList.size; i++){
ElementClass x = myList.get(i);
//Do some more stuff
}
}
}
The question is how can I stop run() from accesing myList when doJob is executed and viceversa?
Imagine this: I start the thread and start adding elements to my list. At a random moment I call doJob() from another class that holds a reference to my thread.
How should I do the lock? Thanks!
L.E.
Ok, I understood the concept of the lock, but now I have another question.
Suppose I have a class with public static myList and only one instance of that class. From that instance I create n instances of Thread that take every element of that list and do some stuff with it.
Now, at a specific moment, myList is updated. What happens with those Threads that already were processing myList elements? How should I lock access on myList while updating it?

NOTE: This code assumes you only have one instance of MyClass. according to your post that sounds like the case.
public class MyClass extends Thread implements Observer{
private List<AnotherClass> myList = null;
private Object lock = new Object();
public MyClass(List<AnotherClass> myList){
this.myList = new ArrayList(myList);
}
public void run(){
while(true){
//Do some stuff
synchronized(lock) {
myList.add(NotImportantElement);
}
}
}
public void doJob{
synchronized(lock) {
for(int i=0; i<myList.size; i++){
ElementClass x = myList.get(i);
//Do some more stuff
}
}
}
}
EDIT: Added making a copy of List so that external entities could not change the list as per JB Nizet
EDIT 2: Made variables private so nobody else can access them

You can:
Declare both run and doJob synchronized. This will use this as lock;
Declare list as final and synchronize on it. This will use list as lock. Declaring lock field as final is good practice. This way some methods of your class my synchronize on one object, while other methods can use other object for synchronization. This reduces lock contention but increases code complexity;
Introduce explicit java.util.concurrent.locks.Lock variable and use it's methods for synchronization. This will improve code flexibility, but will increase code complexity as well;
Don't do explicit synchronization altogether and instead employ some thread-safe data structure from JDK. For example, BlockingQueue or CopyOnWriteArrayList. This will reduce code complexity and ensure thread safety.
Employ synchronization by reads/writes to volatile field. See this SO post. This will ensure safety, but will increase complexity greatly. On the second thought, don't do this :)

You can either add
synchronized
keyword to both methods OR use the
synchronized(Myclass.class) {
}
The former essentially uses the Myclass.class object but it is not as fine-grained as the latter.

Declare both methods as synchronized to lock every instance, or use a synchronized(this){...} block to make the lock only on the current instance.

synchronized(myList) {
// do stuff on myList
}
Specific documentation: Intrinsic Locks and Synchronization
Yet I encourage you to use a thread-safe concurrent data structure for what you want to achieve to avoid doing synchronizing yourself and to get (a lot) better performance: Concurrent package summary

Related

Thread Safety in Java Using Atomic Variables

I have a Java class, here's its code:
public class MyClass {
private AtomicInteger currentIndex;
private List<String> list;
MyClass(List<String> list) {
this.list = list; // list is initialized only one time in this constructor and is not modified anywhere in the class
this.currentIndex = new AtomicInteger(0);
}
public String select() {
return list.get(currentIndex.getAndIncrement() % list.size());
}
}
Now my question:
Is this class really thread safe thanks to using an AtomicInteger only or there must be an addional thread safety mechansim to ensure thread-safety (for example locks)?
The use of currentIndex.getAndIncrement() is perfectly thread-safe. However, you need a change to your code to make it thread-safe in all circumstances.
The fields currentIndex and list need to be made final to achieve full thread-safety, even on unsafe publication of the reference to your MyClass object.
private final AtomicInteger currentIndex;
private final List<String> list;
In practice, if you always ensure that your MyClass object itself is safely published, for example if you create it on the main thread, before any of the threads that use it are started, then you don't need the fields to be final.
Safe publication means that the reference to the MyClass object itself is done in a way that has a guaranteed multi-threaded ordering in the Java Memory Model.
It could be that:
All threads that use the reference get it from a field that was initialized by the thread that started them, before their thread was started
All threads that use the reference get it from a method that was synchronized on the same object as the code that set the reference (you have a synchronized getter and setter for the field)
You make the field that contains the reference volatile
It was in a final field if that final field was initialized as described in section 17.5 of the JLS.
A few more cases the are not easily used to publish references
I think your code contains two bugs.
First, normally when you receive an object from some unknown source like your constructor does, you make a defensive copy to be certain it is not modified outside of the class.
MyClass(List<String> list) {
this.list = new ArrayList<String>( list );
So if you do this, do you now need to mutate that list anywhere inside the class? If so, the method:
public String select() {
return list.get(currentIndex.getAndIncrement() % list.size());
isn't atomic. What could happen here is a thread call getAndIncrement() and then perform the modulus (%). Then at that point if it's swapped out with another thread that removes an item from the list, the old limit of list.size() will no longer be valid.
I think there's nothing for it but to add synchronized to the whole method:
public synchronized String select() {
return list.get(currentIndex.getAndIncrement() % list.size());
And the same with any other mutator.
(final as the other poster mentions is still required on the instance fields.)

How to make this function thread safe?

public class Sol {
static Map<Integer, List<String>> emap;
static List<Integer> sortSalaries(List<List<String>> workers) {
List<Integer> res = new ArrayList<Integer>();
emap = new HashMap<>();
for (List<String> e: workers)
emap.put(Integer.parseInt(e.get(0)), e);
for(List<String> worker: workers )
{
//accessing workers
.....
}
Collections.sort(res);
return res;
}
public static int dfs(int eid) {
List<String> employee = emap.get(eid);
int salary=0;
String ans = employee.get(3);
for (int i=0;i<ans.length();i=i+2)
{
// accesing emap
......
}
return salary;
}
}
Do i have to use synchronized keyword to make it thread safe. Do i have to use Vector and Hashtable if method is synchronized.
Alternatively, What if i use Vector and Hashtable, move the emap variable to sortSalaries() and pass it to dfs(). Is it okay if i not use synchronized keyword in this case..
I asked you question in comment that - do you understand why these methods are not thread-safe if called from multiple threads? and you pointed me to a link without specifying that if you really understood it or not and why do you think that your class is not thread safe so I am providing a little bit of background instead of directly answering the question.
A Bit of Short Discussion
Any class or its methods might become not thread safe when you start sharing data among runner / calling threads. Your class by default is thread - safe if no data is shared among threads so easiest way to make your class thread - safe is to stop sharing data among threads and in your case, its going to be removal of - emap ( because its a class state and used in methods ) & List<List<String>> workers ( This is what I am not sure of since its a reference passed on from caller and different method calls will be working on same instance or might be different instances are passed to this method ) and replace these by method local variables.
Method local variables are thread - safe by default since new instances are created and destroyed for each call.
if you can't do that or not feasible , follow oleg.cherednik's answer to synchronize for variable - emap - either at block level or method level. Do remember that there are various ways to synchronize in Java with synchronized keyword being easiest.
Now for method parameters - List<List<String>> workers & int eid , synchronization for eid is not needed since you are simply reading it and not updating & also its not pass by reference but pass by value due to type being primitive.
Synchronization for access to List<List<String>> workers is needed if you are passing same list instance to calls of this method from different threads. Refer to Gray's Answer - Here and this point is missed in oleg.cherednik's answer. You are better judge if synchronization would be needed or not for this reference.
Its easy to assume that List iteration is thread- safe ( since you are not updating the list ) but that might not always be true . Refer this question and all answers for detailed discussion.
So summary is this - you start implementing thread - safety for your class by first analyzing if some objects are shared among threads or not. If objects are shared , read / write to those objects need to be synchronized ( to make it atomic & provided those objects are not already thread - safe ) . If no objects are shared - its already thread safe . Also, try to create your classes with already thread - safe data structures , that way you will have less work to do.
java.lang.NullPointerException ( NPE ) point of oleg.cherednik's answer stands too.
Protect emap from outer access
Init emap to exclude NPE
Example:
public final class Sol {
private static final Map<Integer, List<String>> emap = new HashMap<>();
static List<Integer> sortSalaries(List<List<String>> workers) {
synchronized (Foo.class) {
for (List<String> e : workers)
emap.put(Integer.parseInt(e.get(0)), e);
}
// do smth, not access emap
}
public static synchronized int dfs(int eid) {
// do smth with accessing emap
}
}
In sortSalaries you can minimize synchoronized block with for loop. In dfs you access emap in different places of the method and therefore you have to synchoonized enire method.
Using either ConcurrentHashMap or Vector do not help here, becuase betwee get/set elements to the collection, they could be changed, which is not OK for dfs method: it should feeze emap when it's called.

How to avoid synchronization on a non-final field?

If we have 2 classes that operate on the same object under different threads and we want to avoid race conditions, we'll have to use synchronized blocks with the same monitor like in the example below:
class A {
private DataObject mData; // will be used as monitor
// thread 3
public setObject(DataObject object) {
mData = object;
}
// thread 1
void operateOnData() {
synchronized(mData) {
mData.doSomething();
.....
mData.doSomethingElse();
}
}
}
class B {
private DataObject mData; // will be used as monitor
// thread 3
public setObject(DataObject object) {
mData = object;
}
// thread 2
void processData() {
synchronized(mData) {
mData.foo();
....
mData.bar();
}
}
}
The object we'll operate on, will be set by calling setObject() and it will not change afterwards. We'll use the object as a monitor. However, intelliJ will warn about synchronization on a non-final field.
In this particular scenario, is the non-local field an acceptable solution?
Another problem with the above approach is that it is not guaranteed that the monitor (mData) will be observed by thread 1 or thread 2 after it is set by thread 3, because a "happens-before" relationship hasn't been established between setting and reading the monitor. It could be still observed as null by thread 1 for example. Is my speculation correct?
Regarding possible solutions, making the DataObject thread-safe is not an option. Setting the monitor in the constructor of the classes and declaring it final can work.
EDIT Semantically, the mutual exclusion needed is related to the DataObject. This is the reason that I don't want to have a secondary monitor. One solution would be to add lock() and unlock() methods on DataObject that need to be called before working on it. Internally they would use a Lock Object. So, the operateOnData() method becomes:
void operateOnData() {
mData.lock()
mData.doSomething();
.....
mData.doSomethingElse();
mData.unlock();
}
You may create a wrapper
class Wrapper
{
DataObject mData;
synchronized public setObject(DataObject mData)
{
if(this.mData!=null) throw ..."already set"
this.mData = mData;
}
synchronized public void doSomething()
{
if(mData==null) throw ..."not set"
mData.doSomething();
}
A wrapper object is created and passed to A and B
class A
{
private Wrapper wrapper; // set by constructor
// thread 1
operateOnData()
{
wrapper.doSomething();
}
Thread 3 also has a reference to the wrapper; it calls setObject() when it's available.
Some platforms provide explicit memory-barrier primitives which will ensure that if one thread writes to a field and then does a write barrier, any thread which has never examined the object in question can be guaranteed to see the effect of that write. Unfortunately, as of the last time I asked such a question, Cheapest way of establishing happens-before with non-final field, the only time Java could offer any guarantees of threading semantics without requiring any special action on behalf of a reading thread was by using final fields. Java guarantees that any references made to an object through a final field will see any stores which were performed to final or non-fields of that object before the reference was stored in the final field but that relationship is not transitive. Thus, given
class c1 { public final c2 f;
public c1(c2 ff) { f=ff; }
}
class c2 { public int[] arr; }
class c3 { public static c1 r; public static c2 f; }
If the only thing that ever writes to c3 is a thread which performs the code:
c2 cc = new c2();
cc.arr = new int[1];
cc.arr[0] = 1234;
c3.r = new c1(cc);
c3.f = c3.r.f;
a second thread performs:
int i1=-1;
if (c3.r != null) i1=c3.r.f.arr[0];
and a third thread performs:
int i2=-1;
if (c3.f != null) i2=c3.f.arr[0];
The Java standard guarantees that the second thread will, if the if condition yields true, set i1 to 1234. The third thread, however, might possibly see a non-null value for c3.f and yet see a null value for c3.arr or see zero in c3.f.arr[0]. Even though the value stored into c3.f had been read from c3.r.f and anything that reads the final reference c3.r.f is required to see any changes made to that object identified thereby before the reference c3.r.f was written, nothing in the Java Standard would forbid the JIT from rearranging the first thread's code as:
c2 cc = new c2();
c3.f = cc;
cc.arr = new int[1];
cc.arr[0] = 1234;
c3.r = new c1(cc);
Such a rewrite wouldn't affect the second thread, but could wreak havoc with the third.
A simple solution is to just define a public static final object to use as the lock. Declare it like this:
/**Used to sync access to the {#link #mData} field*/
public static final Object mDataLock = new Object();
Then in the program synchronize on mDataLock instead of mData.
This is very useful, because in the future someone may change mData such that it's value does change then your code would have a slew of weird threading bugs.
This method of synchronization removes that possibility. It also is really low cost.
Also having the lock be static means that all instances of the class share a single lock. In this case, that seems like what you want.
Note that if you have many instances of these classes, this could become a bottleneck. Since all of the instances are now sharing a lock, only a single instance can change any mData at a single time. All other instances have to wait.
In general, I think something like a wrapper for the data you want to synchronize is a better approach, but I think this will work.
This is especially true if you have multiple concurrent instances of these classes.

Is static method without any parameters thread-safe?

I have a counter and multiple threads access the getCount method. The code is like the following:
public class ThreadSafeMethod {
public static int counter = 0;
public static int getCount() {
return counter++;
}
}
Is the method thread safe? My understanding is that because counter++ is not atomatic, it is not safe. Then how to make it safe? If we add synchronized keyword, what object will be synchronized?
You are correct in your analysis when you say that it's not thread safe because the operation is not atomic. The retrieval of the value and the increment are not thread safe. Multiple calls to this method (whether it has parameters or not) access the same non-local variable.
Adding synchronized to this method makes it thread-safe. When adding to a static method, then the Class object is the object which is locked.
An alternative to making it thread-safe is to replace the int with an AtomicInteger, which has its own atomic getAndIncrement method.
No, a parameter-less method is not inherently thread-safe - the lack of parameters makes no difference in this example.
The read from (and write to) the counter variable is not guaranteed to be either atomic or consistent between threads.
The simplest change is to simply make the method synchronized:
public static synchronized int getCount() {
return counter++;
}
(The simplest is not always the "best" or "correct", but it will be sufficient here, assuming that no other code touches the public counter variable.)
See this answer for how a synchronization of a static method works - as can be imagined, it is the Class itself that is used as the monitor.
Using the synchronised keyword on the static function will 'lock' the function to one thread at a time to ensure that two threads can not mess with the same variable. With what you propose, I believe anything that gets accessed or modified in that function will be thread safe.
Just as you say the counter++ operation is non atomic so giving multiple threads access at once will result in undefined behaviour. In thread safety, the issue is almost always having synchronized access to shared resources such as static variables.
The lock which a thread acquires when declaring the method synchronized belongs to that class. Say we had two methods in a class
public synchronized void foo() {...}
public synchronized void bar() {...}
If one thread enters foo() it acquires the lock for the class, and any other thread trying to access foo() OR bar() will block until the first thread has finished. To overcome this, we can lock on seperate objects within the methods.
// Declare 2 objects to use as locks within the class
private Object fooLock = new Object();
private Objecy barLock = new Object();
// lock on these objects within the method bodies
public void foo {
synchronized(fooLock) { /* do foo stuff */ }
}
public void bar() {
synchronized(barLock) {/* do bar stuff */}
}
Now 2 threads can access the foo() and bar() simultaneously.
There's a lot of material on the web on Thread safety, I'd recommend this set of tutorials if yo want to know more about multithreading with locks / executor services and stuff.

Synchronization on static and instance method

I am confused about synchronizing an instance method and a static method.
I want to write a thread safe class as follow :
public class safe {
private final static ConcurrentLinkedQueue<Object> objectList=
new ConcurrentLinkedQueue<Object>();
/**
* retrieves the head of the object and prints it
*/
public synchronized static void getHeadObject() {
System.out.println(objectList.peek().toString());
}
/**
* creates a new object and stores in the list.
*/
public synchronized void addObject() {
Object obj=new Object();
objectList.add(obj);
}
}
Synchronizing on a static method will lock on safe.class lock and synchronizing on a instance method will lock on this .and hence an inconsistent state will be reached.
If I want to achieve a consistent state for a below code snippet how can that be achieved?
First, ConcurrentLinkedQueue does not require explicit synchronization. See this answer.
Second, you always can synchronize object you are accessing:
public class safe {
private final static ConcurrentLinkedQueue<Object> objectList=
new ConcurrentLinkedQueue<Object>();
/**
* retrieves the head of the object and prints it
*/
public static void getHeadObject() {
synchronized(objectList){
System.out.println(objectList.peek().toString());
}
}
/**
* creates a new object and stores in the list.
*/
public void addObject() {
Object obj=new Object();
synchronized(objectList){
objectList.add(obj);
}
}
}
EDIT: I'm assuming you meant Queue<Object> objectList instead of ConcurrentLinkedQueue<Object> objectList. ConcurrentLinkedQueue<Object> already does all of your thread safety for you, meaning you can call objectList.peek() all you want without worrying about race conditions. This is great if you're developing multi-threaded programs but not so great for learning about thread safety.
Your methods need not be synchronized, assuming you have one thread operating on one instance of the object at a time, but however if you need to have multiple instances of the class that all refer to the same static class variable, you need to synchronized over the class variable like so:
public static void getHeadObject() {
synchronized(safe.objectList) {
System.out.println(objectList.peek().toString());
}
}
This locks the objectList and does not allow it to be read or written to in any other thread as soon as the program is inside the synchronization block. Do the same for all other methods to be synchronized.
NOTE:
However, since you are doing only one simple get operation List.peek(), you really don't need to synchronize over the objectList since in a race condition, it'll get either one value of the List or another. The problem with race conditions is when multiple complex read/write operations are performed, with the value changing in between them.
For example, if you had a class PairInt with a PairInt.x and PairInt.y fields, with the constraint that x = 2y, and you wanted to do
System.out.println(myIntPair.x.toString() + ", " + myIntPair.y.toString());
and another thread was updating the value of x and y at the same time,
myIntPair.y = y + 3;
myIntPair.x = 2 * y;
And the write thread modified myIntPair in between your read thread's myIntPair.x.toString() and myIntPair.y.toString() you might get an output that looks like (10, 8), which means if you are operating on the assumption that x == 2 * y could crash your program.
In that case, your read needs to use a synchronized, but for more simpler things like peek() on a simple object that is being added or deleted, not modified while in the queue, the synchronized can, in most cases be dropped. In fact, for string, int, bool, and the like, the synchronized condition for a simple read should be dropped.
However, writes should always be synchronized on operations that are not explicitly thread safe, i.e. already handled by java. And as soon as you acquire more than one resource, or require that your resource stay the same throughout the operation as you do multiple lines of logic to it, then you MUST USE synchronized
A few comments:
Java conventions:
class names should be in CamelCase (i.e. call your class Safe, not safe)
static comes before synchronized in methods declaration
static comes before final in fields declaration
as others have already said, ConcurrentLinkedQueue is already thread safe, so there is no need for synchronization in the example you give.
mixing static and non static methods the way you do looks weird.
assuming that your actual use case is more complicated and you need a method to run atomic operations, then your code does not work, as you pointed out, because the 2 synchronized methods don't synchronize on the same monitor:
public static synchronized getHeadObject(){} //monitor = Safe.class
public static synchronized addObject(){} //monitor = this
So to answer your specific question, you could use a separate static object as a lock:
public class Safe {
private static final ConcurrentLinkedQueue<Object> objectList =
new ConcurrentLinkedQueue<Object>();
// lock must be used to synchronize all the operations on objectList
private static final Object lock = new Object();
/**
* retrieves the head of the object and prints it
*/
public static void getHeadObject() {
synchronized (lock) {
System.out.println(objectList.peek().toString());
}
}
/**
* creates a new object and stores in the list.
*/
public void addObject() {
synchronized (lock) {
Object obj = new Object();
objectList.add(obj);
}
}
}

Categories