Program with race conditions in Windows, but not in Ubuntu - java

In an assignment designed to highlight race conditions, we were given the following code
public class IncreaseDecrease {
public static int IntegerVariable = 0;
public static final int NUM_ITER = 5000000;
public static void main(String[] args) throws Exception {
Increase inc;
Decrease dec;
while (true) {
inc = new Increase();
dec = new Decrease();
inc.start();
dec.start();
inc.join();
dec.join();
System.out.println(IntegerVariable);
IntegerVariable = 0;
Thread.sleep(750);
}
}
}
class Increase extends Thread {
#Override
public void run() {
for (int i = 0; i < IncreaseDecrease.NUM_ITER; i++) {
IncreaseDecrease.IntegerVariable++;
}
}
}
class Decrease extends Thread {
#Override
public void run() {
for (int i = 0; i < IncreaseDecrease.NUM_ITER; i++) {
IncreaseDecrease.IntegerVariable--;
}
}
}
this code which would be expected to print 0 if each thread can update the value before the other one reads it, but that does not happen due to race conditions, it can print any value between -5000000 and 5000000.
I ran that code on windows and repl.it, and it gave the expected output:
-310951
-1918567
-3374495
-3219135
-2286639
-3221055
-3794319
-2442047
-2776415
-3617391
But on Ubuntu, when I ran it, it gave 0 every time.
My question is, why does this happen? Does Ubuntu manage threads differently, or is it just a special case for my computer?
Edit:
After putting the increment in a different method and adding one more operation to it, I observed the race condition. Here's the final code:
public class IncreaseDecrease {
public static int IntegerVariable = 0;
public static final int NUM_ITER = 5000000;
public static void main(String[] args) throws Exception {
Increase inc;
Decrease dec;
while (true) {
inc = new Increase();
dec = new Decrease();
inc.start();
dec.start();
inc.join();
dec.join();
System.out.println(IntegerVariable);
IntegerVariable = 0;
Thread.sleep(750);
}
}
public static void increment ()
{
IntegerVariable++;
double a = Math.pow(3, 7);
}
public static void decrement()
{
IntegerVariable--;
double a = Math.pow(3, 7);
}
}
class Increase extends Thread {
#Override
public void run() {
for (int i = 0; i < IncreaseDecrease.NUM_ITER; i++) {
IncreaseDecrease.increment();
}
}
}
class Decrease extends Thread {
#Override
public void run() {
for (int i = 0; i < IncreaseDecrease.NUM_ITER; i++) {
IncreaseDecrease.decrement();
}
}
}

I'd go out on a limb and claim that Hotspot under Linux using the server compiler while it doesn't on Windows is the more likely explanation: The compiler can replace the whole loop with a single expression which is something that HotSpot is definitely capable of. Adding any native method will make that impossible thereby making it much more likely to observe the race condition
I would guess that this might be the case as well.
Have you tried making your IntegerVariable volatile? This would prevent some compiler optimization that might occur.
public static volatile int IntegerVariable = 0;

There is a common misconception about threads in Java that they truly and efficiently interleave processing evenly. That is actually not quite true and different JVMs on different systems work differently.
It all arises from when the JVM decides to switch threads. A JVM will probably switch threads whenever it hits a Thread.sleep() or a blocking method such as as synchronized or a lock but generally if a thread is not doing anything that involves blocking etc it will let the thread run.
Your loops ar spinning on incrementing and decrementing a value with no pause. If you add a Thread.sleep(0) call in your loops you will probably see a difference because you are offering the JVM many more opportunities to switch your thread out/in.
for (int i = 0; i < IncreaseDecrease.NUM_ITER; i++) {
IncreaseDecrease.IntegerVariable--;
// Add this.
Thread.sleep(0);
}

Related

Preventing deadlock in two thread program

Suppose I have the following code, where one thread generates squares and writes them to a buffer while another thread prints them:
import java.util.*;
public class Something {
public static Buffer buffer = new Buffer();
public static class Buffer {
private int[] buffer;
private static final int size = 10;
//Indexes for putting and taking element form buffer
private int in, out;
//Number of elements in buffer
private int k;
public Buffer() {
buffer = new int[size];
in = 0;
out = 0;
k = 0;
}
public synchronized void put(int e) {
try {
while (k == buffer.length) {
wait();
}
} catch (InterruptedException ex) {
}
buffer[in] = e;
k++;
in = ++in % size;
notifyAll();
}
public synchronized int take() {
try {
while (k == 0) {
wait();
}
} catch (InterruptedException ex) {
}
int e = buffer[out];
buffer[out] = 0;
out = ++out % size;
k--;
notifyAll();
return e;
}
public synchronized boolean notEmpty() {
return k != 0;
}
}
public static class Generator implements Runnable {
int limit;
public Generator(int lim) {
limit= lim;
}
#Override
public void run() {
for (int i = 1; i < limit; i++) {
buffer.put(i * i);
}
}
}
public static class Printer implements Runnable {
private Thread[] generators;
public Printer(Thread[] gen) {
generators = gen;
}
public synchronized boolean nobody() {
for (Thread th : generators) {
if (th.isAlive()) {
return false;
}
}
return true;
}
#Override
public void run() {
int x = 0;
while (!nobody() || buffer.notEmpty()) {
x = buffer.take();
System.out.println(x);
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread generator = new Thread(new Generator(69));
Thread printer = new Thread(new Printer(new Thread[]{generator}));
generator.start();
printer.start();
generator.join();
printer.join();
}
}
Generator should generate squares of numbers until it reaches some limit (limit = 69, in this case). Printer should print all values generated by Generator. Buffer works somewhat like ring buffer. Indexes for putting (in) and taking (out) element are cycling in bounds of buffer size. Buffer has methods for putting and taking elements from buffer. Generator thread cannot put elements in buffer if it is full (that is, there are no zero elements; zero element is 0, for precision sake...). Printer works this way: first it checks if there are any alive generator threads and then checks if buffer contains only zero elements. If neither of these conditions is true, printer thread terminates.
Now, to the problem. I always get printed all squares from 1 to 68, which is expected output of this program. However, on very rare occasion after all numbers had been output I get a deadlock. How rarely? Well, maybe in 1 out of 100 executions of program. I had to keep hitting "F6" on NetBeans like crazy to get a deadlock. And yes, I know that I can test this simply putting all main code in for loop.
Conversely, if I comment out print line in Printers' run method, deadlock happens almost all the time. Here:
#Override
public void run() {
int x = 0;
while (!nobody() || buffer.notEmpty()) {
x = buffer.take();
//System.out.println(x);
}
}
I do not expect this behavior, because element still gets taken from buffer and generator should be awoken.
Why does this happen? And how do I fix it?
Sorry if question isn't clear enough, I'll try to clarify it as best I can if needed.
I think I fount the problem. Here is what I got: There is a very short moment in time, where the Generator thread is still alive (i.e. Thread.isAlive() will return true), but the Generator has left the for-loop within run(). If the Printer queries its while-condition within its run() at this point in time, it will try to take() something, that is not there (and never will be). Indeed, you can verify, that the Generator always finishes, meaning termination detection on the side of the Printer is faulty. For a hot fix, you can simply add a magic constant is Printers while condition:
#Override
public void run() {
int x = 0;
int count = 0;
while (++count < 69) {
x = buffer.take();
System.out.println(x);
}
}
For a clean termination detection, you could set some common flag-variable to false, signaling that the Generator has finished work and the Printer can stop working. But this has to be done in a synchronized manner, meaning the Printer is not allowed to query this condition, while the Generator is after its last push, but before it sets this common flag.

JVM seems to stop context switching very quickly

I'm implementing the naive version of the Producer-Consumer concurrency problem. And it the threads are switched between at first very quickly but then stop around i = 50. Adding additional print statements for some reason allows the JVM to context switch the threads and complete the program.
Why doesn't the JVM context switch the threads so that the program will complete?
// Producer - Consumer problem
// Producer constantly puts items into array, while consumer takes them out
class IntBuffer {
private int[] buffer;
private int index;
public IntBuffer(int size) {
buffer = new int[size];
index = 0;
}
public void add(int item) {
while (true) {
if (index < buffer.length) {
buffer[index] = item;
index++;
return;
}
}
}
public int remove() {
while (true) {
if (index > 0) {
index--;
int tmp = buffer[index];
buffer[index] = 0;
return tmp;
}
}
}
public void printState() {
System.out.println("Index " + index);
System.out.println("State " + this);
}
public String toString() {
String res = "";
for (int i = 0; i < buffer.length; i++) {
res += buffer[i] + " ";
}
return res;
}
}
class Producer extends Thread {
private IntBuffer buffer;
public Producer(IntBuffer buffer) {
this.buffer = buffer;
}
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("added " + i);
buffer.add(i);
}
}
}
class Consumer extends Thread {
private IntBuffer buffer;
public Consumer(IntBuffer buffer) {
this.buffer = buffer;
}
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("removed " + i);
buffer.remove();
}
}
}
public class Main {
public static void main(String[] args) {
IntBuffer buf = new IntBuffer(10);
Thread t1 = new Thread(new Producer(buf));
Thread t2 = new Thread(new Consumer(buf));
t1.start();
t2.start();
System.out.println(buf);
}
}
Your question does not provide enough details to give an answer with a confidence(at least, it is not clear where those additional print statements go), so I'll make some(reasonable) guesses here.
Your code is not correct. IntBuffer is not thread-safe, but it is accessed from multiple threads.
Any operations on the IntBuffer do not establish a happens-before relationship, so the changes made by one thread may be not visible for another thread. That's why the Producer thread can "believe" that the buffer is full while the Consumer thread "believes" that it is empty. In this case the program never terminates.
This two statements are not guesses, they are facts based on the Java memory model. And here goes my guess why the additional print statements sorta fix it:
In many JVM implementations, the println methods uses syncronization internally. That's why a call to it creates a memory fence and makes changes made in one thread visible to the other one, eliminating the issue described in 2).
However, if you really want to solve this problem, you should make the IntBuffer thread-safe.
At the minimum you need the volatile keyword on both the buffer and index. Second, you need to access index only once under the true arm of the ifs you have there. Even after that, you will face out of bounds access at 10, you will need more fixing to work around that. Your buffer is de facto stack. So, even after all of this, your remove() can be working with stale index, thus you will be removing in the middle of the stack. You could use 0 as special value marking the slot already handled end empty.
With all of this, I do not think your code is easily salvageable. It pretty much needs complete rewrite using proper facilities. I agree with #kraskevich:
#StuartHa Naive usually means simple(and most likely inefficent) solution, not an incorrect one.

Strange concurrent code behavior

I'm currently in the process of learning Java concurrency. And I am very surprised by the way following code behaves.
import java.util.concurrent.*;
public class Exercise {
static int counter = 0;
static synchronized int getAndIncrement() {
return counter++;
}
static class Improper implements Runnable {
#Override
public void run() {
for (int i = 0; i < 300; i++) {
getAndIncrement();
}
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 300; i++) {
executorService.submit(new Improper());
}
executorService.shutdown();
System.out.println(counter);
}
}
Shouldn't it output 90000 all the time? Instead the result differs all the time.
executorService.shutdown() doesn't wait for the service to shut down. You need a call to awaitTermination.
you access the counter from the main method without locking. I think you would narrowly escape a data race if you waited for the executor service to shut down, but be warned that, in general, you must synchronize on all accesses of a shared variable, not just writes, to have any visibility guarantees from the Java Memory Model.
You need to make sure that all tasks have had time to terminate. Use awaitTermination
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 300; i++) {
executorService.submit(new Improper());
}
executorService.shutdown();
executorService.awaitTermination(2, TimeUnit.SECONDS);
System.out.println(counter);
}
You don't wait for all your submited tasks to terminate, see the javadoc for ExecutorService.html#shutdown. So gettting an arbitrary output each time is the expected behabiour.

How to make one thread object stop the other thread object in java

I have a class here that will be used as a thread/Runnable object, the second class below (UseSearch) has a main method that intantiates two instances of the Search class and uses them to create two threads. As you can see, the run method calls the add method that runs the loop depending on the direction passed in. I am looking for a mechanism that will cause one of the threads to stop the other thread's loop from iterating when the other thread has finished running it's iteration. Any help/advise will be highly appreciated. I have seen a similar example but it's far too complex for me to comprehend. - Jevison7x
public class Search implements Runnable
{
int sum;
boolean direction;
String name;
public Search(String n, boolean positive)
{
this.direction = positive;
this.name = n;
}
void add()
{
if(direction == true)
{
for(int i = 0; i < 100; i++)
{
sum += 1;
System.out.println(name+" has "+sum);
}
}
else
{
for(int i = 0; i < 100; i++)
{
sum -= 1;
System.out.println(name+" has "+sum);
}
}
}
public void run()
{
add();
}
}
public class UseSearch
{
public static void main(String[] args)
{
Search s1 = new Search("bob", true);
Search s2 = new Search("dan", false);
Thread t1 = new Thread(s1);
Thread t2 = new Thread(s2);
t1.start();
t2.start();
}
}
The thread that is doing the iterating needs to test something on each iteration to see if it has been told to stop. That could be a custom flag (implemented in a variety of ways) or a the thread's interrupted flag.
If you are going to use interrupt, then Matt Clark's answer is half of the picture. The other half is that the iterating thread needs to do something like this:
if (Thread.currentThread.isInterrupted()) {
// pause or stop or break out of the loop or whatever
}
... in the body of the relevant loop or loops.
Note: there is no safe way in Java to stop or pause another thread that is not regularly checking to see if it should stop / pause; i.e. a thread that is not cooperating.
Long answer short...
Make the Threads class-wide variables so that each thread has access to the other:
Thread t1, t2;
public static void main(String[] args){
t1 = new Thread(){
public void run(){
t2.interrupt();
}
};
t2=new Thread(){
public void run(){
t1.interrupt();
}
};
}

Semaphores: Critical Section with priorities

I'm writing a program in Java that deals with Semaphores for an assignment. I'm still new to the idea of Semaphores and concurrency.
The description of the problem is as follows:
A vector V[] of booleans. V[i] is "True"if Pi needs to use the critical section.
A vector of binary semaphores B[] to block processes from entering their critical section: B[i] will be the semaphore blocking process Pi.
A special scheduler process SCHED is used whenever a blocked process needs to be awakened to use the critical section.
SCHED is blocked by waiting on a special semaphore S
When a process Pi needs to enter the critical section, it sets V[i] to "True", signals the semaphore S and then waits on the semaphore B[i].
Whenever SCHED is unblocked, it selects the process Pi with the smallest index i for which V[i] is "True". Process Pi is then awakened by signaling B[i] and SCHED goes back to sleep by blocking on semaphore S.
When a process Pi leaves the critical section, it signals S.
This is my code:
import java.util.concurrent.Semaphore;
public class Process extends Thread {
static boolean V[];
int i;
static Semaphore B[]; //blocking semaphore
static Semaphore S;
private static int id;
static int N;
static int insist = 0;
public static void process (int i, int n) {
id = i;
N = n;
V = new boolean[N];
}
private void delay () {
try {
sleep (random(500));
}
catch (InterruptedException p) {
}
}
private static int random(int n) {
return (int) Math.round(n * Math.random() - 0.5);
}
private void entryprotocol(int i) {
V[Process.id] = true;
int turn = N;
while (V[Process.id] == true && turn == N) {
System.out.println("P" + Process.id + " is requesting critical section");
signal(S);
}
critical(Process.id);
wait(B[Process.id]);
V[Process.id] = false;
}
private void wait(Semaphore S) {
if (Process.id > 0) {
Process.id--;
} else {
//add Process.id to id.queue and block
wait(B[Process.id]);
}
}
private void signal(Semaphore S) {
if (B[Process.id] != null) {
Sched(Process.id);
} else {
Process.id++; //remove process from queue
critical(Process.id); //wakes up current process
}
}
private void critical(int i) {
System.out.println("P" + Process.id + " is in the critical section");
delay();
exitprotocol(i);
}
private void exitprotocol(int i) {
System.out.println("P" + Process.id + " is leaving the critical section");
V[id] = false;
signal(S);
}
public void Sched(int i) {
if (B[Process.id] == null) {
signal(B[Process.id]);
}
wait(S);
}
public void run() {
for (int i = 0; i < 5; i++) {
Sched(i);
entryprotocol(Process.id);
try {
wait(Process.id);
}
catch (InterruptedException p) {
}
signal(S);
}
}
public static void main (String[] args) {
int N = 5;
Process p[] = new Process[N];
for (int i = 0; i < N; i++) {
p[i] = new Process();
p[i].start();
}
}
}
I believe my logic here is correct but I'm getting a lot of errors (such as Exception in thread "Thread-1" java.lang.NullPointerException). Can any shed some light on what I'm doing wrong & provide me with some help. It's greatly appreciated!
Your NPE is probably due to the fact that you never initialize your Semaphore array - but its hard to say without a proper stack trace.
Two pieces of advice:
1) You might want to give your class variables more meaningful names than :
B
N
S
V.
Imagine walking away from this project and revisiting it in 4 months and had to read through that.
2) Figure out your class model on on a white board before writing any code. You have methods that take semaphores with the same name as some of your static fields. What are the relationships of the objects in your program? If you don't know, odds are your program doesn't know either.

Categories

Resources