java synchronised positives/negatives and usage - java

I've read all the theory I can on how synchronised methods operate, but I need a practical example.
What is the positive and negative or using synchronised like this:
public class Test {
public static void main(String[] args){
boolean sync = Boolean.valueOf(args[0]);
Person person1 = person2 = new Person();
person1.write(sync, args[1]);
person1.read(sync);
person2.write(sync, args[1]);
person2.read(sync);
}
}
write is naming the project: (either synchronized or not)
public static String project_name = "";
and read is printing the current name for the person (either synchronized or not)
So what is the difference when write and read are regular methods versus synchronised methods?
What could go wrong if I use the regular method?

Quick answer:
A non-synchronous method being accessed by multiple sources will generally cause undefined behaviour, but a synchronised method will work every time.
Longer answer:
I don't think you fully understand what a synchronised method is, because your code does not demonstrate it at all.
If there really is a possibility of 100 people accessing the same method then you will have undefined behaviour when the same variable is being written to and read from.
However, if that method is accessed synchronously then each method call will be added to a queue and will happen in order.
For example:
100 different threads(People?) could call SynchronizedProjectName.renameProject("exampleName"); and/or SynchronizedProjectName.projectName(); on the code below, and no error would occur, and no read/write would happen at the same time.
public class SynchronizedProjectName {
private string project_name = "";
public synchronized void renameProject(String newProjectName) {
project_name = newProjectName;
}
public synchronized string projectName() {
return project_name;
}
}
You should always always use some sort of thread safe strategy when dealing with multiple threads/users, and if you don't, then you should expect your code to misbehave and probably crash.
See here for a little bit of extra info: https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

Related

Volatile and Synchronized to Solve Race Condition: Singleton Member Field

I was having some problem trying to understand and fix errors reported from Fortify scan. I have this class:
public class DaoImpl extends BaseDaoImpl {
private static volatile String sNric;
synchronized private void setInfo(InfoTO pers) {
sNric = pers.getNRIC();
}
synchronized public InfoTO getInfo() {
InfoTO pers = new InfoTO();
sNric = retrieveDetail();
pers.setNRIC(sNric);
}
synchronized private String retrieveDetail() {
// some logic to get info from database
}
}
My code was originally without the static volatile and synchronized keyword. And Fortify was reporting Race Condition: Singleton Member Field warning at the variable declaration of sNric as well as sNric = retrieveDetail();
I went to research and found this solution. However, I am not very sure on the concept of volatile with synchronized. Will the proposed solution above causing some deadlock issue?
The "concept" of volatile with synchronized is that you probably shouldn't do it.
If you use synchronized in all of the methods that access and update a shared variable (such as your sNric variable) then declaring the volatile is redundant and inefficient.
As to your question about deadlocks, I cannot see any way that you could get deadlocks based solely on the code above. However, you haven't shown us the code for the InfoTO or the code that uses these classes. It is not impossible for a deadlock to occur involving the DaoImpl instance lock and other locks.
If you are concerned that getInfo calling this.retrieveDetail might deadlock. There is only one (DaoImpl instance) lock involved here, and Java primitive locks are reentrant. (A thread will not be blocked if it tries to acquire a primitive lock that it already holds.)
Finally, you should if you are concerned about thread-safety, check that setNRIC and getNRIC are thread-safe. If they are not, I don't think that the above is handling the InfoTo objects safely.
Note that you cannot reason about the thread-safety of a class unless you take account of the other classes that it depends on AND the way that it used / intended to be used.
You have not really given enough information and code details for a certain Answer. But I will give it a shot.
AtomicReference
To quote the comment above by scottb:
Thread safety of shared variables is about visibility and atomicity of state transitions.
I often prefer the use of the Atomic… classes to address both visibility and atomicity. These classes can provide an alternative to volatile and synchronized.
In this case, we can use AtomicReference class to hold as its payload a reference to your current desired String value. Notice that we mark it final as the reference to the AtomicReference object itself will never change. Its payload, a reference (pointer) taking us to the desired String object, does change. At one moment it may point to the String value "dog" while a moment later it may point to the String value "cat". But the container of either String is always the very same AtomicReference object, a wrapper around that contained text, that contained String object.
If your InfoTO class looked like this:
package work.basil.example;
public class InfoTO
{
private String nric ;
public String getNric ( ) { return this.nric; }
public void setNric ( String nric ) { this.nric = nric; }
}
…then your DaoImpl might look something like this:
package work.basil.example;
import java.util.concurrent.atomic.AtomicReference;
public class DaoImpl
{
private AtomicReference < String > sNric;
private void setInfo ( InfoTO pers )
{
this.sNric.set( pers.getNric() );
}
public InfoTO getInfo ( )
{
InfoTO pers = new InfoTO();
String s = retrieveDetail();
pers.setNric( s );
return pers ;
}
private String retrieveDetail ( )
{
return this.sNric.get();
}
}
Your lines:
sNric = retrieveDetail();
pers.setNRIC(sNric);
…do not make sense to me. You use a field to hold what is a temporary value. So I substituted a local variable instead.
Your retrieveDetail method makes no sense to me. You seem to be returning from calls to a database the very same string value you are caching in the field sNric. So I changed that method to access the cached field sNric. This seems more consistent with your intended logic, and more importantly, shows both the getter and setter of the AtomicReference in action.
Of course, as others said, you may well have other thread-safety issues in the substantial code you did not show us.

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.

How to deal with one time execution of "code piece" or method?

I come across this kind of a situation a lot.
class A{
public static boolean flag = true;
public void method(){
// calls method in class B
B b = new B();
while(someCondition){
b.method();
}
}
}
.
class B{
public void method(){
if(A.flag){
// Read all data from a flat file and store it in HashMAp/ArrayList etc
//only for the first time
A.flag = false;
}
// Manipulate the data
}
}
I seem to be running into this type of situation quite often in completely different situations.
Is this how it is normally dealt with? I feel a bit silly and unnatural using static variables and if statements to resolve the issue.
In this case, I don't want to cause an overhead by reading data every time the method is executed.
It looks like you need the Singleton Pattern. Figure out what data B needs to load upon its first use, and package that into a separate class that gets used as a singleton instance. See this link for more information on how to implement the singleton pattern in Java.
Following this pattern, you can avoid the need for checking a flag every time your method is called, and you can simultaneously avoid any threading issues (if there are any).
As John B pointed out, a simple check for null should be enough rather than using a flag. If thread safety becomes an issue, you might also look into Guava's CacheBuilder and Suppliers.memoize() for these types of situations.
Rather than reading an external flag to determine if the data has already been stored, why not check the data store to see if it is populated? Or if the data store is expensive (DB) use a local static variable rather than one in a different class.
You could simply check if the list/map that stores your data has been initialised by a previous call
class A {
public void method() {
B b = new B();
while (someCondition) {
b.method();
}
}
}
class B {
private List myList;
public void method() {
if (myList == null) {
// Read all data from a flat file and store it in myList
}
// manipulate the data
}
}

Multithreading headache. Java. Return values

Hi guys I have the following.
class a extends Thread
{
public synchronized BigInteger getUniqueID()
{
BigInteger aUniqueID = new BigInteger(getUniqueKeyFromDatabase);
return aUniqueID;
}
}
class b extends a
{
public run()
{
BigInteger uniquieID = getUniqueID();
// store UniqueID in another database table with other stuff
}
}
And what I'm getting is duplicate unique id stored in the database table. I'm assuming because uniqieID is being changed in this multi threaded environment.
I'm obviously going horribly horribly wrong somewhere, I'm guessing I shouldn't be returning the value in this way. Or should be defining uniqueID as new BigInteger based on the response from the getUniqueID method.
Any help would be greatly appreciated, as my fragile mind has been warped right now!
Cheers
Alan
BigInteger is an (from the JavaDocs)
Immutable arbitrary-precision integer
So that rules out anyone mutating the BigInteger object. I'd look into getUniqueKeyKeyFromDatabase
You getUniqueKeyFromDatabase() has to be a method which will not return the same value twice. Everything else doesn't matter.
Each thread has it own copy of local variables are they are not shared.
BTW: don't extend Thread, its bad practice which often leads to confusion.
Your problem is because you're not really synchronizing anything. The getUniqueID() method in class A is synchronized on its own implicit monitor. But that means each time you create a new thread, you're synchronizing each one on itself. Does that make sense ?
You need to synchronize on some shared variable. A quick fix to illustrate the point (but really don't use this in practice) is: In the example below all your threads are synchronizing on the same object ( a shared static ).
class A extends Thread {
static Object shared = new Object();
public BigInteger getUniqueID()
{
synchronize (shared) {
BigInteger aUniqueID = new BigInteger(getUniqueKeyFromDatabase);
return aUniqueID;
}
}
}
Chances are, that the synchronized modifier for getUniqueID() is pointless, as you don't modify any state there. It does not protect the getUniqueKeyFromDatabase() either, because it synchronizes on the instance. This means that every Thread runs without synchronizing with the others.
You could try if
public BigInteger getUniqueID() {
synchronized (a.class) {
BigInteger aUniqueID = new BigInteger(getUniqueKeyFromDatabase);
return aUniqueID;
}
}
Works better for you. If it does, you should think about your database design (or whatever happens in getUniqueKeyFromDatabase). Synchonization should really be done by the database, not in client code.
You must have a problem with the method which returns the unique id. To assure uniqueness of your ids for each object use something like below, for example in you class a.
PS: Class names should start from capital letters. Also as suggested by #Peter Lawrey implement Runnable instead of extending a Thread.
private static int nextId = 0;
protected int id;
public a(){
this.id = getNextId();
}
private static int getNextId(){
return nextId++;
}

Is it possible to access static methods of a class by multiple object instances simultaneously?

Example:
ThisClass.staticMethod(Object... parameters);
will be accessed by multiple instances of other objects and simultaneously.
Will there be any dependencies with this other objects when they are using the same static method at the same time?
Only if the method uses static Objects or the arguments are shared by the other instances.
Example: Math.max(int a, int b) is a static method but does not use any static objects, so there are no dependencies.
Example 2: Here all invocations share the same result variable, two parallel calls to staticMethod can cause wrong results.
private static int result = 0;
private static int staticMethod(Object... args)
{
result = args.length;
//Do Something
return result;
}
Example 3: This one is Thread safe if none of the arguments are shared, each invocation has its own instance of result.
private static int staticMethod(Object... args)
{
int result = 0;
result = args.length;
//Do something
return result;
}
Example 4: This uses the class as a lock to prevent parallel access to the class functions. Only one call to staticMethod executes all others wait
private static int result = 0;
private static synchronized int staticMethod(Object... args)
{
result = args.length;
//Do Something
return result;
}
A code fragment running concurrently by multiple threads has the potential of causing race conditions, regardless of where this code is placed (static/non-static method).
You must make sure that the data manipulated by the code tolerates concurrent accesses, and synchronize the code properly if needed.
Obviously, all users of the method depend on the class, if this is what you mean.
Moreover, if they are really calling the method simultaneously (i.e. from multiple threads), you may get concurrency problems, depending on what the method actually does. Show us the code, and we may be able to tell more.
All objects that call the static methods will be dependent on the class methods, but they won't have dependencies with each other. If it's possible that your static method will be called by objects from different threads, you will need to make sure that your static method is thread-safe, i.e., you need to using locking to ensure that only one thread at a time accesses any non-stack memory.

Categories