Can this code have race condition? - java

public static void deleteLast(Vector list) {
int lastIndex = list.size() - 1;//line 2
list.remove(lastIndex); // line 3
}
I known Vector is threadsafe in java
but can this case happen
let's say in this case has list.size()=10
Thread A calls deleteLast and at line 2 lastIndex = 9 .It stops for some reason
Thread B call deleteLast and at line 2 lastIndex = 9.it goes to line 3 and now list has 9 elements
Thread A now wakes up and goes to line 3 now it tries to remove object at index 9 which doesn't exist and we have an exception here

Sure. You've correctly identified a race condition.

Yes, it can. And you should use a BlockingQueue rather than a List to avoid this scenario.

Related

parellel search with communications between threads

Suppose I have an int array, an element num and 4 threads.
I'm giving each thread 1/4 of the array to search for num.
(The search method is given below)
public static boolean contains(int[] array, int minIdx, int maxIdx, int num) { ...}
At my "top level", I can schedule 4 threads to search 4 quarters of the array, but how do I ensure ALL the threads stop searching as soon as one of them finds the element (assuming there is NO duplicate in the array, hence the element can appear at most once).
P.S: You see, suppose my 4th thread found the element at the first iteration, I want the top-level method to return immediately as opposed to wait for other 3 guys to complete.
You need explicit signaling. You might consider the built-in interruption mechanism, or you may roll your own because it's very simple.
One idea: share an AtomicBoolean among all the threads and let each one periodically check it. When a thread finds the answer, it flips the boolean. The best option to achieve periodic checking is a nested loop:
for (int i = start; i < end && !done.get();) {
for (int batchLimit = Math.min(i + BATCH_SIZE, end); i < batchLimit; i++) {
// your logic
}
}
This is the easiest for the JIT compiler to optimize.
The price of checking the value is very low whenever the value didn't change. It will be in the L3 cache. The case when the value did change is irrelevant because at that point you're done.
Use a flag to signal when you found the answer and share it between threads. AtomicBoolean is a good option.
Add the boolean to your loop end conditions for example
for (int i = minIdxs ; i < maxIdxs && found.get() == false; ++i){...}
Also share a CountDownLatch of size 4 and countDown() when you are returning from each thread.
Have your main thread await() and it'll mean all threads gracefully finish before you move on in your main thread.
You can write a class who will act like a controller. this class will know each thread and every thread knows the controller. (its like an observer pattern)
If one thread finds the answer, the thread can tell it to the controller which can inform the other threads to stop.
class ControllerOfAllTheThreads{
ArrayList<TheClassesWhichDoTheSearch> list = new ArrayList<TheClassesWhichDoTheSearch>();
public void tellThemWeFoundHim(){
for (TheClassesWhichDoTheSearch theThreads : list) {
if(theThreads.isAlive() && !theThreads.isInterrupted())
theThreads.interrupt();
}
}
}

Many independent threads dependent on single thread

I have a file which has n columns and many rows
Col 1 col2 col3 .......col n
I want to read it once and write multiple (say m) outputs grouping the rows by few key columns. Say 3 outputs have to be produced:
For output 1:
groupingKeys[0]={1,2) //group the records on col 1 and 2
For output 2:
groupingKeys[1]={1,4,5} //group the records on col 1 4 5
For output 3
groupingKeys[2]={2,3} //group on col 2,3
In Main-thread I read the input file line by line. For each read line I want to process the read line in m different threads. So basically I want that the calls
map[0].process(data,groupingKeys[0]);
map[1].process(data,groupingKeys[1]);
map[2].process(data,groupingKeys[2]);
should run in 3 different threads and each of the 3 threads should proceed only after main thread has read the line.
I can create m different threads with run method of i-th thread having
map[i].process(data,groupingKeys[i]);
But these 3 threads should proceed only when main-thread which reads the line so that they see correct value of data[]. How can i achieve this?
Main thread thread-0 thread-1 thread-2
running waiting waiting waiting
waiting running running running
running waiting waiting waiting
At each step a line is read and processed
By processed i mean something similar to sql groupby is done for each of the grouping keys
Below is the sample code referred above.
public void writeMultipleGroupedOutputs(String inputfile,int groupingKeys[][])
{
Mymap<key,value>[] mapArr= new Mymap<key,value>[k]; //k maps to group records in k ways as per k grouping keys
String line;
while((line = br.readLine()) != null) {
String[] data=line.split(regex); **//one line is read in main thread**
for(int i=0;i<m;i++)
map[i].process(data,groupingKeys[i]); **//process in m different ways.How to make this happen in m independent threads?**
}
class Mymap extends HashMap<key,value> {
void process(String[] data,int[] keyIndexes)
{
//extract key from key indexes
//extract value from value indexes
put(key,value);
}
#Override
public Value put(Key k, Value v) {
if (containsKey(k)) {
oldval=get(k);
put(k,oldval.aggregate(v)); //put sum of old and new
return oldval;
}else{
put(k,v);
return null;
}
}
}
}
Sorry if i haven't made my point clear.In simple words the i want map[i].process(data,groupingKeys[i]); to happen in separate(i-th thread)
a b 5
a b 10
a c 15
so if i want to group by {1} and {1,2}
read line map1 map2
a b 5 [a--> b,5] [a,b ->5]
a b 10 [a-> b 15] [a,b->15]
a c 15 [a->b 30] [a,b->15 a,c->15]
Edit:
The question is not related to how i process or the logic of grouping but it is that: After each line is read i want to do something with the read line in different threads.
If I understand correctly, you wish to wait with processing until all the file is read. If so, depending on the details, you may want to check out CyclicBarrier or CountDownLatch
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html

Is id = 1 - id atomic?

From page 291 of OCP Java SE 6 Programmer Practice Exams, question 25:
public class Stone implements Runnable {
static int id = 1;
public void run() {
id = 1 - id;
if (id == 0)
pick();
else
release();
}
private static synchronized void pick() {
System.out.print("P ");
System.out.print("Q ");
}
private synchronized void release() {
System.out.print("R ");
System.out.print("S ");
}
public static void main(String[] args) {
Stone st = new Stone();
new Thread(st).start();
new Thread(st).start();
}
}
One of the answers is:
The output could be P Q P Q
I marked this answer as correct. My reasoning:
We are starting two threads.
First one enters run().
According to JLS 15.26.1, it firstly evaluates 1 - id. Result is 0. It is stored on the thread's stack. We are just about to save that 0 to static id, but...
Boom, scheduler chooses the second thread to run.
So, the second thread enters run(). Static id is still 1, so he executes method pick(). P Q is printed.
Scheduler chooses first thread to run. It takes 0 from its stack and saves to static id. So, the first thread also executes pick() and prints P Q.
However, in the book it's written that this answer is incorrect:
It is incorrect because the line id = 1 - id swaps the value of id between 0 and 1. There is no chance for the same method to be executed twice.
I don't agree. I think there is some chance for the scenario I presented above. Such swap is not atomic. Am I wrong?
Am I wrong?
Nope, you're absolutely right - as is your example timeline.
In addition to it not being atomic, it's not guaranteed that the write to id will be picked up by the other thread anyway, given that there's no synchronization and the field isn't volatile.
It's somewhat disconcerting for reference material like this to be incorrect :(
In my opinion, the answer in the Practice Exams is correct. In this code, you are executing two threads which have access to the same static variable id. Static variables are stored on the heap in java, not on the stack. The execution order of runnables is unpredictable.
However, in order to change the value of id each thread :
makes local copy of the value stored in id's memory address to the CPU registry;
performs the operation 1 - id. Strictly speaking, two operations are performed here (-id and +1);
moves the result back to memory space of id on the heap.
This means that although the id value can be changed concurrently by any of the two threads, only the initial and final values are mutable. Intermediate values will not be modified by one another.
Futhermore, analysis of the code can show that at any point in time, id can only be 0 or 1.
Proof:
Starting value id = 1;
One thread will change it to 0 ( id = 1 - id ). And the other thread will bring it back to 1.
Starting value id = 0;
One thread will change it to 1 ( id = 1 - id ). And the other thread will bring it back to 0.
Therefore, the value state of id is discrete either 0 or 1.
End of Proof.
There can be two possibilities for this code:
Possibility 1. Thread one accesses the variable id first. Then the value of id (id = 1 - id changes to 0. Thereafter, only the method pick () will be executed, printing P Q. Thread two, will evaluate id at that time id = 0; method release() will then be executed printing R S. As a result, P Q R S will be printed.
Possibility 2. Thread two accesses the variable id first. Then the value of id (id = 1 - id changes to 0. Thereafter, only the method pick () will be executed, printing P Q. Thread one, will evaluate id at that time id = 0; method release() will then be executed printing R S. As a result, P Q R S will be printed.
There are no other possibilities. However, it should be noted that variants of P Q R S such as P R Q S or R P Q S, etc. may be printed due to pick() being a static method and is therefore shared between the two threads. This leads to the simultaneous execution of this method which could result in printing the letters in a different order depending on your platform.
However in any case, never will either the method pick() or release () be executed twice as they are mutually exclusive. Therefore P Q P Q will not be an output.

Lock Free Circular Array

I am thinking about implementing a lock free circular array. One problem is maintaining the head and tail pointers in a lock free manner. The code I have in mind is:
int circularIncrementAndGet(AtomicInteger i) {
i.compareAndSet(array.length - 1, -1);
return i.incrementAndGet();
}
Then I would do something like:
void add(double value) {
int idx = circularIncrementAndGet(tail);
array[idx] = value;
}
(Note that if the array is full old values will be overwritten, I am fine with that).
Does anyone sees a problem with this design? I suspect there might be a race condition I am not seeing.
A simpler approach is to use a power of 2 size and do the following.
final double[] array;
final int sizeMask;
final AtomicInteger i = new AtomicInteger();
public CircularBuffer(int size) {
assert size > 1 && ((size & (size -1)) == 0); // test power of 2.
array = new double[size];
sizeMask = size -1;
}
void add(double value) {
array[i.getAndIncrement() & sizeMask] = value;
}
Check out disruptor : http://lmax-exchange.github.io/disruptor/, it's an open-source lock-free circular buffer in Java.
Yes, there is a race condition.
Say i = array.length - 2, and two threads enter circularIncrementAndGet():
Thread 1: i.compareAndSet(array.length - 1, -1) results in i = array.length - 2
Thread 2: i.compareAndSet(array.length - 1, -1) results in i = array.length - 2
Thread 1: i.incrementAndGet() results in i = array.length - 1
Thread 2: i.incrementAndGet() results in i = array.length
leading to an ArrayIndexOutOfBoundsException when Thread 2 reaches array[idx] = value (and on all subsequent calls to add() until i overflows).
The solution proposed by #Peter Lawrey does not suffer from this problem.
If you stick with the following constraints:
Only one thread is allowed to modify the head pointer at any time
Only one thread is allowed to modify the tail pointer at any time
Dequeue-on-empty gives a return value indicating nothing was done
Enqueue-on-full gives a return value indicating nothing was done
You don't keep any count of how many values are stored in the queue.
You 'waste' one index in the array that will never be used, so that you can tell when the array is full or empty without having to keep count.
It is possible to implement a circular array/queue.
The enqueuing thread owns the tail pointer. The dequeueing thread owns the head pointer. Except for one condition, these two threads don't share any state so far, and so there are no problems.
That condition is testing for emptyness or fullness.
Consider empty to mean that head == tail; Consider full to mean tail == head - 1 modulo array size. Enqueue has to check to see if the queue is full, dequeue has to check to see if the queue is empty. You need to waste one index in the array to detect the difference between full and empty - if you enqueued into that last bucket, then full would be head == tail and empty would be head == tail and now you deadlock - you think you're empty and full at the same time, so no work would get done.
In performing these checks, its possible that one value could be updated while being compared. However since these two values are monotonically increasing, there is no correctness problem:
If, in the dequeue method, the head == tail computes to be true during the comparison, but tail moves forward just afterward, no problem - you thought the array was empty when it actually wasn't, but no big deal, you'll just return false from the dequeue method and try again.
If, in the enqueue method, the tail == head - 1 computes to be true, but just after so the head increments, then you'll think the array was full when it really wasn't, but again, no big deal, you'll just return false from enqueue and try again.
This is the design used behind the implementation I found in Dr. Dobb's years ago, and it has served me well:
http://www.drdobbs.com/parallel/lock-free-queues/208801974

Java atomic classes in compound operations

Will the following code cause race condition issue if several threads invoke the "incrementCount" method?
public class sample {
private AtomicInteger counter = new AtomicInteger(0);
public int getCurrentCount {
int current = counter.getAndIncrement();
if (counter.compareAndSet(8, 0)) current = 0;
return current;
}
}
If it causes race condition, what are the possible solution other than using synchronized keyword?
You probably don't want to let the counter exceed 8 and this won't work. There are race conditions.
It looks like you want a mod 8 counter. The easiest way is to leave the AtomicInteger alone and use something like
int current = counter.getAndIncrement() & 7;
(which is fixed and optimized version of % 8). For computations mod 8 or any other power of two it works perfectly, for other number you'd need % N and get problems with int overflowing to negative numbers.
The direct solution goes as follows
public int getCurrentCount {
while (true) {
int current = counter.get();
int next = (current+1) % 8;
if (counter.compareAndSet(current, next))) return next;
}
}
This is about how getAndIncrement() itself works, just slightly modified.
Yes, it probably does not do what you want (there is a kind of race condition).
One thread may call getAndIncrement() and receive a 8
A second thread may call getAndIncrement() and receive a 9
The first thread tries compareAndSet but the value is not 8
The second thread tries compareAndSet but the value is not 8
If there's no risk of overflowing, you could do something like
return counter.getAndIncrement() % 8;
Relying on that something does not overflow seems like a poor idea to me though, and I would probably do roughly what you do, but let the method be synchronized.
Related question: Modular increment with Java's Atomic classes
What are you trying to achieve? Even if you use the fixes proposed by ajoobe or maartinus you can end up with different threads getting the same answer - consider 20 threads running simultaneously. I don't see any interesting significance of this "counter" as you present it here - you may as well just pick a random number between 0 and 8.
Based on the code for getAndIncrement()
public int getCurrentCount() {
for(;;) {
int courrent = counter.get();
int next = current + 1;
if (next >= 8) next = 0;
if (counter.compareAndSet(current, next))
return current;
}
}
However a simpler implementation in your case is to do
public int getCurrentCount() {
return counter.getAndIncrement() & 0x7;
}
I assume that the what you want is to have a counter form 0 to 7.
If that is the case then a race condition can possibly happen and the value of counter can become 9.
Unless you are ok to use % soln. as said by others, you micht have to use synchronized.

Categories