Santosh
Santosh

Reputation: 852

Java Thread : Multithreading - Race condition

I am writing multi-threading program which can be accessed from multiple user simultaneously and that program has to avoid race conditions.

Code / multi-threading :

public class DataProcessor implements Serializable, Runnable {

private static final long serialVersionUID = 1L;

public DataProcessor() {

}

@Override
public void run() {
    process();
}

private void process() {

    int iSize = 5;

    for (int iCounter = 0; iCounter < iSize; iCounter++) {
        DataKey objDataKey = new DataKey();
        ArrayList<String> list = //..fetch data method ()
        HashMap<String, String> hmPQdata = //..fetch data method ()

        SendNForgotHelperThread helperThread = new SendNForgotHelperThread(objDataKey, list, hmPQdata);
        Thread t = new Thread(helperThread);
        t.start();
    }

}

class SendNForgotHelperThread implements Runnable {

    private ArrayList<String> list;
    private HashMap<String, String> hmPQdata;
    private DataKey objDataKey;

    public SendNForgotHelperThread(DataKey objDataKey, ArrayList<String> list, HashMap<String, String> hmPQdata) {
        this.list = list;
        this.hmPQdata = hmPQdata;
        this.objDataKey = objDataKey;
    }

    @Override
    public void run() {

        try {

            // Option 1 : synchronized method - SendNForgotHelperThread class object locking

            DataCollector objDataSenderM = new DataCollector();
            objDataSenderM.synchronizedMethodStore(this.objDataKey, this.list, this.hmPQdata);

            // Option 2 : synchronized block - SendNForgotHelperThread class object locking

            synchronized (this) {
                DataCollector objDataSender = new DataCollector();
                objDataSender.store(this.objDataKey, this.list, this.hmPQdata);
            }

            // Option 3 : Class level locking

            synchronized (SendNForgotHelperThread.class) {
                DataCollector objDataSender = new DataCollector();
                objDataSender.store(this.objDataKey, this.list, this.hmPQdata);
            }

        } catch (Exception iex) {
            System.out.println("Exception in thread: " + iex.getMessage());
        }
    }
}

class DataCollector {

    public void store(DataKey objDataKey, ArrayList<String> list, HashMap<String, String> hmPQdata) {

        HashMap<String, String> retrivedValue = (HashMap<String, String>) MemCacheUtil
                .retrieveFromMemCache(objDataKey.getKey());

        retrivedValue.putAll(hmPQdata);

        MemCacheUtil.addToMemCache(objDataKey.getKey(), retrivedValue, "expTime value");

        // Sending data in queue
        sendDataToQueue(objDataKey, list, hmPQdata);

    }

    synchronized void synchronizedMethodStore(DataKey objDataKey, ArrayList<String> list,
            HashMap<String, String> hmPQdata) {
        store(objDataKey, list, hmPQdata);

    }

}

class DataKey {
    private String key;

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }
}

public void sendDataToQueue(DataKey objDataKey, ArrayList<String> list, HashMap<String, String> hmPQdata) {
    // sending data to queue

}

}

User 1 :

public class UserA {

public static void main(String[] args) {
    DataProcessor objDataProcessor = new DataProcessor();
    Thread thProcessorThread = new Thread(objDataProcessor, "PROCESSOR");
    thProcessorThread.start();
}

}

User 2 :

public class UserB {

public static void main(String[] args) {
    DataProcessor objDataProcessor = new DataProcessor();
    Thread thProcessorThread = new Thread(objDataProcessor, "PROCESSOR");
    thProcessorThread.start();
}

}

User A & B will be call DataProcessor thread at same time. It is clear that Option 1 & 2 will be face race conditions as they are locking object of that class / self class object locking and option 3 will provide lock on class level - if multiple user will access the program at same time then option 3 will slow the application and whole purpose of the multi-threading will go on toss.

Could any one please advise any read-up on how to handle this scenario.

Edit :

Could any one please help to handle race condition on SendNForgotHelperThread thread object - this thread being called from loop and for each loop new thread SendNForgotHelperThread being started.

Upvotes: 2

Views: 735

Answers (1)

Saravana
Saravana

Reputation: 12817

You're passing two different instance of DataProcessor to the threads in class UserA and UserB, if you start these main methods it will run normally. the race-condition won't occur in your application.

For race-condition to occur you have to pass the shared object, i.e. multiple threads to operate on a same object and the shared objects should have field/attribute to get shared between multiple threads

    DataProcessor objDataProcessor = new DataProcessor();
    Thread thProcessorThread1 = new Thread(objDataProcessor, "PROCESSOR-1");
    thProcessorThread1.start();
    Thread thProcessorThread2 = new Thread(objDataProcessor, "PROCESSOR-2");
    thProcessorThread2.start();

Upvotes: 2

Related Questions