Is static method without any parameters thread-safe? - java

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.

Related

Does synchronizing on the static field that you are modifying make your code thread safe?

class A {
private static BigInteger staticCode = BigInteger.ZERO;
private BigInteger code;
public A() {
synchronized(staticCode) {
staticCode = staticCode.plus(BigInteger.ONE);
code = staticCode;
}
}
}
I'm not an expert in concurrency by any means. Could someone explain to me why the class provided above isn't thread safe?
What are the situations that can cause a race condition? My thought process is that if we create 10 instances of this class, every instance will synchronize on a different value of staticCode and that's why it's thread safe, but I was told that it wasn't. But why?
I know that we can synchronize on .class and it will definitely be thread safe, but I still want to understand this particular situation.
Does synchronizing on the static field that you are modifying make your code thread safe?
No, because you're reassigning it. (*)
As soon as that reassignment has taken place, you've effectively lost the mutual exclusion on access to the staticCode field.
Any thread which is already waiting at the synchronized block before the assignment will continue to wait.
Any thread which arrives at the synchronized block after the reassignment but before the reassigning thread has left the block will attempt to synchronize on the new value of staticCode.
A more subtle point than the fact you don't have mutual exclusion is that you also lose the happens-before between the end of the synchronized block and the start of the next execution. This means that you don't have guaranteed visibility of the updated value, so you can potentially generate multiple instances of A with the same code.
It's a bad idea to synchronize on a non-final member. If you don't want to synchronize on A.class, you can define an auxilliary member on which to synchronized:
class A {
private static final Object lock = new Object();
private static BigInteger staticCode = BigInteger.ZERO;
public A() {
synchronized (lock) {
staticCode = ...
}
}
}
This preserves the mutability of staticCode, but allows correct mutual exclusion.
However, an Atomic* class would be far easier because you avoid the need to synchronize (e.g. AtomicInteger or AtomicLong - but if you really think you're going to have more than 2^63 things, you can use an AtomicReference<BigInteger>):
class A {
private static final Object lock = new Object();
private static AtomicReference<BigInteger> staticCode = new AtomicReference<>(BigInteger.ZERO);
public A() {
BigInteger code;
do {
code = staticCode.get();
} while (!staticCode.compareAndSet(code, code.add(BigInteger.ONE)));
this.code = code;
// Even easier with AtomicInteger/Long:
// this.code = BigInteger.valueOf(staticCode.incrementAndGet());
}
}
(*) But anyway, dispense with the notion that synchronizing automatically makes something thread safe. For one thing, you need to define precisely what you mean by "thread safe"; but then, you need to understand what synchronization actually provides for you, in order to evaluate whether those things satisfy your thread safety requirements.
I guess the main point I was missing here is that we synchronize on objects, not references to objects.
Consider a situation where I synchronize on BigInteger.ZERO, and then enter the synchronized block.
When the value of staticCode has changed and become BigInteger.ONE, this block still continues to be synchronized on BigInteger.ZERO. Meanwhile another thread is already synchronized on BigInteger.ONE, before we even had a change to assign BigInteger.ONE to code. That second thread could bump staticCode to the value of 2, and now both threads are before the second assignment, but the value of staticCode is 2, so they can both assign the same value of staticCode to 2 different instances of the class.

How to solve this "Synchronize on a new "Object" instead. "

I am getting the warning in sonar at line synchronized (new Integer(count)) as
Synchronize on a new "Object" instead.
public class PRMDataTransferHelper {
/** static variable to keep count */
private static int count = 0;
private static void done() {
synchronized (new Integer(count)) {
count--;
if (0 == count) {
cleanUp();
}
}
return;
}
}
There are two problems here:
As Sonar states, you shouldn't synchronize on a primitive wrapper (i.e. Integer, Long, Boolean, etc.) since these can be created by autoboxing, and Sonar assumes that this is risky. It is risky because a lock object used in a synchronized statement should be constant among all threads that are to be synchronized. Any dynamic object that may be re-used in the program logic can easily lead to failed synchronization. Therefore, it is best practise to instantiate Object and create a special lock object that is used for synchronization only.
You are using new Integer(count), i.e. whenever the synchronized block is entered, a new instance of integer is created. This means that each thread will see its own version of a lock object, and thus the block will not be synchronized between threads at all. In order to achieve synchronization, you need to re-use a lock object shared by all threads.
In your case, having a static variable such as
private static Object lock=new Object();
and using this one in synchronized(lock) would ensure that all threads are indeed synchronized at the beginning of the block.

Is this code thread-safe or is using a parameter to synchronize risky? [duplicate]

Take this code:
public class MyClass {
private final Object _lock = new Object();
private final MyMutableClass _mutableObject = new MyMutableClass()
public void myMethod() {
synchronized(_lock) { // we are synchronizing on instance variable _lock
// do something with mutableVar
//(i.e. call a "set" method on _mutableObject)
}
}
}
now, imagine delegating the code inside myMethod() to some helper class where you pass the lock
public class HelperClass {
public helperMethod(Object lockVar, MyMutableClass mutableVar) {
synchronized(lockVar) { // we are now synchronizing on a method param,
// each thread has own copy
// do something with mutableVar
// (i.e. call a "set" method on mutableVar)
}
}
}
can "myMethod" be re-written to use the HelperClass by passing its lock var, so that everything is still thread safe? i.e.,
public void myMethod() {
_helperObject.helperMethod(_lock, _mutableObject);
}
I am not sure about this, because Java will pass the lockVar by value, and every thread will get a separate copy of lockVar (even though each copy points to the same object on the heap). I guess the question comes down to how 'synchronized' keyword works -- does it lock on the variable, or the value on the heap that the variable references?
Synchronization is done upon objects, not variables.
Variables/members [sometimes] contain objects and it is the resulting object contained in [variable] x that is actually synchronized upon in synchronized(x).
There are a few other issues with thread-visibility of variables (e.g. might read a "stale" object from a variable), but that does not apply here: there is no re-assignment of _lock and the visibility of the initial ("final") assignment is guaranteed. Because of this it is guaranteed that, in this case, the method parameter will always contain the correct (same) object used for the synchronization.
If the lock object used (where presumably _lock is not final) changes, however, then that would require re-evaluation of the appropriate values/thread-visibility but otherwise does not differ from any cross-thread access.
Happy coding.

synchronized in java - Proper use

I'm building a simple program to use in multi processes (Threads).
My question is more to understand - when I have to use a reserved word synchronized?
Do I need to use this word in any method that affects the bone variables?
I know I can put it on any method that is not static, but I want to understand more.
thank you!
here is the code:
public class Container {
// *** data members ***
public static final int INIT_SIZE=10; // the first (init) size of the set.
public static final int RESCALE=10; // the re-scale factor of this set.
private int _sp=0;
public Object[] _data;
/************ Constructors ************/
public Container(){
_sp=0;
_data = new Object[INIT_SIZE];
}
public Container(Container other) { // copy constructor
this();
for(int i=0;i<other.size();i++) this.add(other.at(i));
}
/** return true is this collection is empty, else return false. */
public synchronized boolean isEmpty() {return _sp==0;}
/** add an Object to this set */
public synchronized void add (Object p){
if (_sp==_data.length) rescale(RESCALE);
_data[_sp] = p; // shellow copy semantic.
_sp++;
}
/** returns the actual amount of Objects contained in this collection */
public synchronized int size() {return _sp;}
/** returns true if this container contains an element which is equals to ob */
public synchronized boolean isMember(Object ob) {
return get(ob)!=-1;
}
/** return the index of the first object which equals ob, if none returns -1 */
public synchronized int get(Object ob) {
int ans=-1;
for(int i=0;i<size();i=i+1)
if(at(i).equals(ob)) return i;
return ans;
}
/** returns the element located at the ind place in this container (null if out of range) */
public synchronized Object at(int p){
if (p>=0 && p<size()) return _data[p];
else return null;
}
Making a class safe for multi-threaded access is a complex subject. If you are not doing it in order to learn about threading, you should try to find a library that does it for you.
Having said that, a place to start is by imagining two separate threads executing a method line by line, in an alternating fashion, and see what would go wrong. For example, the add() method as written above is vulnerable to data destruction. Imagine thread1 and thread2 calling add() more or less at the same time. If thread1 runs line 2 and before it gets to line 3, thread2 runs line 2, then thread2 will overwrite thread1's value. Thus you need some way to prevent the threads from interleaving like that. On the other hand, the isEmpty() method does not need synchronization since there is just one instruction that compares a value to 0. Again, it is hard to get this stuff right.
You can check the following documentation about synchronized methods: http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
By adding the synchronized keyword two things are guaranteed to happen:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
So whenever you need to guarantee that only one thread accesses your variable at a time to read/write it to avoid consistency issues, one way is to make your method synchronized.
My advice to you is to first read Oracle's concurrency tutorial.
A few comments:
Having all your methods synchronized causes bottlenecks
Having _data variable public is a bad practice and will difficult concurrent programming.
It seems that you are reimplementing a collection, better use existing Java's concurrent collections.
Variable names would better not begin with _
Avoid adding comments to your code and try to have declarative method names.
+1 for everybody who said read a tutorial, but here's a summary anyway.
You need mutual exclusion (i.e., synchronized blocks) whenever it is possible for one thread to create a temporary situation that other threads must not be allowed to see. Suppose you have objects stored in a search tree. A method that adds a new object to the tree probably will have to reassign several object references, and until it finishes its work, the tree will be in an invalid state. If one thread is allowed to search the tree while another thread is in the add() method, then the search() function may return an incorrect result, or worse (maybe crash the program.)
One solution is to synchronize the add() method, and the search() method, and any other method that depends on the tree structure. All must be synchronized on the same object (the root node of the tree would be an obvious choice).
Java guarantees that no more than one thread can be synchronized on the same object at any given time. Therefore, no more than one thread will be able to see or change the internals of the tree at the same time, and the temporary invalid state created inside the add() method will be harmless.
My example above explains the principle of mutual exclusion, but it is a simplistic and inefficient solution to protecting a search tree. A more practical approach would use reader/writer locks, and synchronize only on interesting parts of the tree rather than on the whole thing. Practical synchronization of complex data structures is a hard problem, and whenever possible, you should let somebody else solve it for you. E.g., If you use the container classes in java.util.concurrent instead of creating your own data structures, you'll probably save yourself a lot of work (and maybe a whole lot of debugging).
You need to protect variables that form the object's state. If these variables are used in static method, you have to protect them as well. But, be careful, following example is wrong:
private static int stateVariable = 0;
//wrong!!!!
public static synchronized void increment() {
stateVariable++;
}
public synchronized int getValue() {
return stateVariable;
}
It seems that above is safe, but these methods operate on different locks. Above is more or less corresponds to following:
private static int stateVariable = 0;
//wrong!!!!
public static void increment() {
synchronized (YourClassName.class) {
stateVariable++;
}
}
public synchronized int getValue() {
synchronized (this) {
return stateVariable;
}
}
Notice that different locks are used when mixing static and object methods.

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