Java: Fail in synchronizing threads - java

I have the following code:
for (int iThreadCounter = 1; iThreadCounter <= CONNECTIONS_NUM; iThreadCounter++){
WorkThread wt = new WorkThread(iThreadCounter);
new Thread(wt).start();
m_arrWorkThreadsToCreate.add(wt);
}
Those threads calls the following code:
int res = m_spLegJoin.call(m_workTread, m_workTread.getConfId());
And this is the call method inside LegJoinSp class:
public class LegJoinSp extends ConnEventSp {
private static final int _LEG_JOIN_ACTION_CODE = 22;
private static int m_nLegId = Integer.valueOf(IniUtils.getIniValue("General", "LEG_ID_START"));
private final Lock m_lock = new ReentrantLock();
public int call(WorkThread a_workThread, String a_sConfId) {
synchronized (this) {
//m_lock.lock();
m_nLegId++;
boolean bPass = false;
Log4jWrapper.writeLog(LogLevelEnum.DEBUG, "LegJoinSp - call", "a_workThread = " + a_workThread.getThreadId() + " a_sConfId = " + a_sConfId);
if (super.call(a_workThread, a_sConfId, _LEG_JOIN_ACTION_CODE, "" + m_nLegId) == 0) {
bPass = true;
} else {
bPass = false;
}
//m_lock.unlock();
if (bPass) {
Log4jWrapper.writeLog(LogLevelEnum.DEBUG, "LegJoinSp - call", "a_workThread = " + a_workThread.getThreadId() + " a_sConfId = " + a_sConfId + " returned leg id " + m_nLegId);
return m_nLegId;
} else {
return -1;
}
}
}
public Lock getLock() {
return m_lock;
}
}
I've got 2 threads calling this call() method.
m_nLegId is initiated with 100.
As you can see I have tried to lock the method with both
synchronized(this)
and
m_lock.lock() and m_lock.unlock()
The problem is that when I first get to if (bPass) inner code, it write 102 to my log as the m_nLegId value. However I expect it to be 101 because of the m_nLegId++; statement.
It seems that the second thread manage to get inside the code before the synchronize block ends for the first thread execution.
How can I fix that?
Thank you

For me your bug is related to the fact that m_nLegId is a static field and you try to synchronize access on the current instance instead of the class such that you don't properly prevent concurrent modifications of your field.
I mean
synchronized (this) {
Should rather be
synchronized (LegJoinSp.class) {
NB: In case you only need a counter, consider using an AtomicInteger for your field instead of an int.

The thing is you are creating a new object with every thread, but the way you applied the lock is applicable only to same object (as you applied the lock on the this).
So if you want to apply the lock on the class level, then you can create a static object and apply the lock on that object which can serve the purpose you wanted to achieve (if I understood your problem correctly based on the comments)

Related

How to prevent context switch in a critical section

I have the following code :
import java.util.ArrayList;
public class main {
final static Object lock= new Object();
public static void main(String[] args) {
for (int i = 0; i < 100000; i++) {
System.out.println("-------");
finish finished = new finish(false);
ArrayList<Boolean> arr = new ArrayList<>();
Thread t1 = new Thread(() -> {
System.out.println(Thread.currentThread().getId() + " Is setting");
finished.setFinished(true);
});
t1.start();
synchronized (lock){
if (finished.isFinished == false) {
System.out.println(Thread.currentThread().getId() + " Is adding");
arr.add(new Boolean(finished.isFinished));
} else {
System.out.println("Done");
}
}
System.out.println("The length of array is " + arr.size());
if (arr.size() > 0) {
System.out.println("The val of array is " + arr.get(0));
}
}
}
}
class finish {
public boolean isFinished = false;
public finish(boolean finished) {
this.isFinished = finished;
}
public void setFinished(boolean finished) {
this.isFinished = finished;
}
}
I am expecting to get the following output :
The length of array is 1
The val of array is false
or
Done
It is the case most of the times.
But sometimes the output is :
The length of array is 1
The val of array is true
It means, that there was a context switch in the critical section.
I have tried to synchronized the code on an object, but it did not help.
It is a classical synchronization problem, I but was not able to solve it.
Maybe I should use atomic objects, but I have no idea how would they help in this case.
Or perhaps I am to harsh with java, and I should not test it in a for loop? I am running this example on a Linux OS.
I think my synchronization does not make sense. But I don't know how to solve it.
It's not at all clear what your example code is trying to do, but if you want to wait for the thread to finish, use t1.join() and deal with the InterruptedException that this throws. Also, finished should be an AtomicBoolean if you're going to use it in more than one thread.
But all in all, the code is pretty problematic, and doesn't reflect whatever real-life scenario you're trying to deal with.
In this code you are reading the same variable twice, which allows for the possibility it can be changed. The simplest solution is to read it just once.
boolean isFinished = finished.isFinished;
if (isFinished) {
System.out.println("Done");
} else {
System.out.println(t1 + " Is adding");
arr.add(isFinished);
}

Making code thread safe

I am trying to see if this code is thread safe.
private void eventProcessing(final AcEvent acEvent){
String tree = null;
String symbol = null;
try {
if(acEvent.isDatafileTransaction()){
final AcEventDatafileTransaction datafileTransaction = acEvent.getDatafileTransaction();
tree = datafileTransaction.getTreeId();
symbol = datafileTransaction.getSymbol();
System.out.println(tree, symbol);
}
}
Do I need to make methods in AcEvent or ACEventDatafileTransaction synchronized. Both these classes just have only get methods as you saw in the code. I am thinking regardless of the number of threads, it will not have a problem in accessing the right values for tree and symbol. Can I say this code is thread safe or do I need to make any changes to make it thread safe?
I am putting eventprocessing in Callable
threadpool.submit(new Callable<Integer>(){
public Integer call() throws Exception{
eventProcessing(event);
}
});
EDIT :
These are two lines after what I have written in eventprocessing.
final List<AcStreamAble> transactions = getDatafileTransactions(datafileTransaction);
final List<AcEventRecordOperation> recordOperations = getTransactionsAsListOfRecordOperations(datafileTransaction, transactions);
I am adding a couple of methods that will come next. Tell me if this will change anything.
private List<AcEventRecordOperation> getTransactionsAsListOfRecordOperations(final AcEventDatafileTransaction datafileTransaction, final List transactions) {
final List <AcEventRecordOperation> recordOperations = new ArrayList<AcEventRecordOperation>(transactions.size());
int i = 0;
for (final Object o : transactions) {
if (!datafileTransaction.isRecordOperation(o)) {
log.debug( "[" + i + "] Ignored transaction - was not a RecordOperation" );
} else {
recordOperations.add(datafileTransaction.convert(o));
}
}
return recordOperations;
}
In the above method, even though there is a list and objects are added to it. I am thinking since it an internal variable, it will be thread safe.
private List<AcStreamAble> getDatafileTransactions(final AcEventDatafileTransaction datafileTransaction) throws IOException {
final List<AcStreamAble> transactions = new ArrayList<AcStreamAble>();
datafileTransaction.addTransactions(transactions);
return transactions;
}
Here since datafileTransaction object is different for different threads. I am assuming it is thread safe.

Something wrong with the Peterson algorithm logic?

I am pretty new to Multithreading programming. In my code threads are trying to acquire locks around few lines. The lines work pretty fine for few context switches but then it halts (probably a deadlock).
On the other hand if use synchronized block then all works fine.
I've four classes.
1. PetersonAlgorithm.java
package com.ashish.master;
public class PetersonAlgorithm {
boolean wantCS[] = {false, false};
int turn = 1;
public void requestCS(int i) {
System.out.println("Lock requested by the thread - " + i);
wantCS[i] = true;
turn = 1 - i;
while(wantCS[1-i] && turn == 1-i);
}
public void releaseCS (int i) {
wantCS[i] = false;
turn = i - 1;
System.out.println("Lock released by the thread - " + i);
}
}
If anyone feels that above algorithm is incorrect then let me know, and feel free to make suggestions.
2. Runner.java
package com.ashish.master;
public class Runner {
public static Incrementer runnableInstance = new Incrementer();
public static Thread inc1 = new Thread(runnableInstance, "0");
public static Thread inc2 = new Thread(runnableInstance, "1");
public static void main(String args[]) {
inc1.start();
inc2.start();
try{
inc1.join();
inc2.join();
} catch (InterruptedException ex) {
System.out.println("The threads have been interrupted while waiting for the join ---> " + ex.getMessage());
}
System.out.println("The total turns taken by incrementer are ----> " + runnableInstance.turns);
}
}
3. Incrementer.java - If synchronized block is used instead of the Peterson algorithm, everything works fine.
package com.ashish.master;
public class Incrementer implements Runnable {
public long turns = 0;
public PetersonAlgorithm pa = new PetersonAlgorithm();
#Override
public void run() {
System.out.println("Thread " + this.toString() + "started.....");
while(true) {
pa.requestCS(Integer.parseInt(this.toString()));
// synchronized(this) {
if(DataStore.data < 1000000) printCriticalSection();
else break;
// }
pa.releaseCS(Integer.parseInt(this.toString()));
}
}
public void printCriticalSection() {
System.out.println("The value of the number is increased by thread " +
this.toString() +" to --> " + DataStore.increase());
turns ++;
}
#Override
public String toString() {
return Thread.currentThread().getName();
}
}
4. DataStore.java A class to mock the data source -- simply increase the number
package com.ashish.master;
public class DataStore {
public static long data = 0L;
public static long increase() {
DataStore.data += 1;
return DataStore.data;
}
}
Your runnables never observe each other's monitors (wantCS and turn) as they have different instances... Each runnable needs to work with a same shared set of monitors!
Take the blue pill and make your PetersonAlgorithm variables static volatile with synchronized block access...
Or take the red pill and you create a Class for your flag monitors (wantCS) and for your indicator monitor (turn). Then just define your runnable with one "own flag", one "observed flag" and one "indicator". Both Runnables will have the same indicator instance (therefore needs to be synchronized) while the flag instances will be crossed (the own flag of R1 will be the observed flag of R2 and the own flag of R2 the observed flag of R1). You should synchronized the flag methods too as you don't want to have a flag raised or lowered while being observed.
Then few steps:
Runnables raise their Flag
Runnables turn the shared Indicator ( set to opponent runnable's id )
Wait if opponent's flag is raised and Indicator is set to opponent.
The non waiting opponent does its stuff then lowers its flag.
The waiting opponent stops waiting (opponent's flag has been lowered), does its stuff and lowers its flag.
Each of your runnable instances has its own PetersonAlgorithm instance. Thus, the two runnables don't know anything about each other and will both always get immediate access to the critical section. Try implementing your PetersonAlgorithm class as static class with static methods. Then change the lines
pa.requestCS(Integer.parseInt(this.toString()));
// ...
pa.releaseCS(Integer.parseInt(this.toString()));
into
PetersonAlgorithm.requestCS(Integer.parseInt(this.toString()));
// ...
PetersonAlgorithm.releaseCS(Integer.parseInt(this.toString()));

Java: What type of list to use in my multi-threaded app

I'm new to using threads and just trying to figure things out. My end game is to have a list of URLs, my program will take one URL from the list at a time and perform an action using that URL. There'll be a lot of URLs and this list may possibly be added to while some threads are using the same list.
To start experimenting and learning I'm using a simple ArrayList filled with numbers and am using a threaded pool to get the URLs. Here's my code:
public static void main(String[] args) {
for (int i = 0; i < 200; i++){
test.add(i);
}
SlothTest runner = new SlothTest();
Thread alpha = new Thread(runner);
Thread beta = new Thread(runner);
ExecutorService tasker = Executors.newFixedThreadPool(10);
while (!listEmpty()){
tasker.submit(new SlothTest());
}
tasker.shutdown();
System.out.println("Complete...");
}
#Override
public void run() {
getLink();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
}
}
private synchronized String getLink(){
link = Thread.currentThread().getName() + " printed " + test.indexOf(test.size()-1);
test.remove(test.size()-1);
System.out.println(link);
return link;
}
private synchronized static boolean listEmpty(){
if (test.size() > 0){
return false;
} else {
return true;
}
}
I'm running into some concurrency issues while running the program and getting some -1's for my output. I'm not sure why this is happening and I know my above code is rough but I'm really in the learning stage a multi-threaded apps. Can anyone help me first off with fixing my concurrency issue and then if you can give me any pointers about my above code that would also be great
One problem is that
while (!listEmpty()){
tasker.submit(new SlothTest());
}
is not atomic. So listEmpty might return false, but become true by the time you reach the next statement.
Another one is that you synchronize on two different monitors:
private synchronized String getLink(){ //synchronized on this
private synchronized static boolean listEmpty(){//synchronized on this.class
Have you considered using a BlockingQueue instead of a list, which has useful methods for what you are trying to achieve.
Try using a ConcurrentLinkedQueue for your list of URLs. This is a good implementation often used in producer-consumer examples, similar to yours (although you don't have an active 'producer', per-se).
You're not globally synchronizing. By using synchronized methods you are locking the current instance, which is different for each task. You should use a global lock instead:
final static Object globalLock = new Object();
private String getLink() {
synchronized (globalLock) {
link = Thread.currentThread().getName() + " printed " + test.indexOf(test.size()-1);
test.remove(test.size()-1);
}
System.out.println(link);
return link;
}
private boolean listEmpty(){
synchronized (globalLock) {
if (test.size() > 0){
return false;
} else {
return true;
}
}
}

Java HashMap sometimes returning wrong value in some threads

Update: It was a static buried deep in some code where it was used for just a couple of instructions. Thank you all for the suggestions.
We are not using one HashMap across threads (yes that is bad for many reasons). Each thread has its own HashMap.
We have a class that extends from Thread. In Thread.run() we create a HashMap, set a key/value pair in it, and pass that HashMap to a method. That method retrieves the value from the HashMap, inserts it into a string, and returns the string.
Sometimes the returned string has a different value (still in Thread.run()). This only occurs on hardware with 3+ physical cores. And it has only happened twice (before we added logging to help us find exactly what is going on of course).
Any idea why this would occur.
Update: here's the full code. The ProcessTxt is what pulls the value from the HashMap and puts it in the string.
import java.io.*;
import java.util.HashMap;
import junit.framework.TestCase;
import net.windward.datasource.dom4j.Dom4jDataSource;
import net.windward.xmlreport.ProcessReport;
import net.windward.xmlreport.ProcessTxt;
/**
* Test calling from multiple threads
*/
public class TestThreads extends TestCase {
private static String path = ".";
// JUnit stuff
public TestThreads(String name) {
super(name);
}
// Get logging going - called before any tests run
protected void setUp() throws Exception {
ProcessReport.init();
}
// this is not necessary - called after any tests are run
protected void tearDown() {
}
private static final int NUM_THREADS = 100;
private boolean hadWithVarError = false;
/**
* Test that each thread has unique variables.
*/
public void testRunReportsWithVariables() throws Exception {
// run 10 threads
ReportThreadWithVariables[] th = new ReportThreadWithVariables[NUM_THREADS];
for (int ind = 0; ind < NUM_THREADS; ind++) {
th[ind] = new ReportThreadWithVariables(this, ind);
th[ind].setName("Run " + ind);
}
for (int ind = 0; ind < NUM_THREADS; ind++)
th[ind].start();
boolean allDone = false;
while (!allDone) {
Thread.sleep(100);
allDone = true;
for (int ind = 0; ind < NUM_THREADS; ind++)
if (th[ind].isAlive())
allDone = false;
}
assertTrue(!hadWithVarError);
}
public static class ReportThreadWithVariables extends Thread {
private TestThreads obj;
private int num;
public ReportThreadWithVariables(TestThreads tt, int num) {
obj = tt;
this.num = num;
}
public void run() {
try{
System.out.println("starting " + num);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ProcessTxt pt = new ProcessTxt(new FileInputStream(new File(path, "Thread_Test.docx")), out);
pt.processSetup();
// don't use order1.xml, but need a datasource.
Dom4jDataSource datasource = new Dom4jDataSource(new FileInputStream(new File(path, "order1.xml")));
HashMap map = new HashMap();
map.put("num", new Integer(num));
datasource.setMap(map);
pt.processData(datasource, "");
pt.processComplete();
String result = out.toString().trim();
System.out.println("complete " + num + ", result = " + result);
String expected = "Number: " + num;
if (!result.equals( expected ))
obj.hadWithVarError = true;
assertEquals(expected, result);
} catch (Throwable e) {
obj.hadWithVarError = true;
e.printStackTrace();
}
}
}
}
(edit to format code)
Given the lack of code and based solely on what has been written I am going to hypothesize that something is static. That is, somewhere along the line a static member is being stored to/written from.
num is not mutable and the other variables (string, map) are local so ReportThreadWithVariables looks thread safe. It seems to me that the problem is in the calls to external objects rather than what you posted.
Are the classes you use documented as Thread Safe?
For exampel, the javadoc of the processData method states that it should not be called multiple times for the same datasource which you seem to be doing (same file name).
ps: (not related) you could use a CountDownLatch instead of the while loop.

Categories