Strange concurrent code behavior - java

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.

Related

How to finish my program after Executor runs in main

I have a problem with finishing my main thread. When threads "finish" (maybe not, I don't know, but I have a right result in static variable "nextNumber"), the program still works.
I suppose that the Executor doesn't terminate because he still waits for another threads to run.
Earlier I used my own runnable class and hadn't to take care about terminating it.
My code:
private static long nextNumber = 0;
public static void main(String[] args) {
Runnable firstCounter = () -> {
for (int i = 0; i < 1000000; i++)
increment("Thread 1");
};
Runnable secondCounter = () -> {
for (int i = 0; i < 1000000; i++)
increment("Thread 2");
};
Executor executor = Executors.newFixedThreadPool(2);
executor.execute(firstCounter);
executor.execute(secondCounter);
System.out.println(nextNumber);
}
synchronized private static void increment(String threadName) {
System.out.println(threadName + " " + ++nextNumber);
}
First you need to use ExecutorService and then you need to shut it down.
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.shutdown(); //Prevents executor from accepting new tasks
executor.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS); //Waits until currently executing tasks finish but waits not more then specified amount of time

Program with race conditions in Windows, but not in Ubuntu

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);
}

why the result is always 101? I think the result should be random since is not thread safe

why the result is always 101?
I think the result should be random since is shareVar not thread safe
public class ThreadQuestion
{
public static int shareVar = 1;
public static void main(String[] args) throws InterruptedException
{
ExecutorService threadPool = Executors.newFixedThreadPool(20);
for(int i = 0; i < 100; i++)
{
threadPool.execute(new Runnable()
{
#Override
public void run()
{
shareVar++;
}
});
}
//wait for other thread finish
Thread.sleep(5000);
System.out.println("shareVar is " + shareVar );
threadPool.shutdown();
}
}
Your concurrent tasks run practically sequential because CPU extremely fast so your task(increment) will run really quick. Your loop execute a bit slower so when you add new task old task will be already executed. Moreover concurrency it's always about theory of chances and 100 it's a small value for getting glitches for this short task.
You should expand loop to bigger value for example to 10000 or even 10000 or just put a tiny delay in your code like this:
for (int i = 0; i < 100; i++) {
threadPool.execute(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(10);
shareVar++;
} catch (InterruptedException ex) {
Logger.getLogger(ThreadQuestion.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
in this case you'll really try to run several threads in the same time and result will change from 101 to about a hundred.

Java stop thread all threads running from class

what I need to do is be able to stop all threads running from one thread class that implements runnable. This is what I mean: here is the beginning of my "thread" class:
public class HTTP extends Thread
{
int threadNumber;
String host;
int port;
int timeLeft;
private BufferedReader LocalBufferedReader;
public HTTP(int threadNumber, String host, int port, int timeLeft)
{
this.threadNumber = threadNumber;
this.host= host;
this.port = port;
this.timeLeft = (timeLeft * 1000);
}
public void run()
{
This is how I am creating the multiple threads to do this:
for (int n = 1; n <= m; n++) {
new HTTP(n + 1, str, j, k).start();
}
m is the number of threads to create. This can be anywhere from 50-1000. Now what I need to do is just abruptly stop all of them at once. How can I do that?
First store all the threads:
ArrayList<Thread> threads = new ArrayList<Thread>();
for (int n = 1; n <= m; n++) {
Thread t = new HTTP(n + 1, str, j, k);
threads.add(t);
t.start();
}
Now for stop method, just loop all the threads and call interrupt on them:
for(Thread thread : threads)
{
thread.interrupt();
}
Make sure to check isIntruppted() in your HTTP threads. So you would do something like this:
public class InterruptTest {
static class TThread extends Thread {
public void run() {
while(!isInterrupted()) {
System.out.println("Do Work!!!");
try {
sleep(1000);
} catch (InterruptedException e) {
return;
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t = new TThread();
t.start();
Thread.sleep(4000);
System.out.println("Sending interrupt!!");
t.interrupt();
Thread.sleep(4000);
}
}
Stopping threads in Java is a cooperative process implemented with interruptions. You could store your threads and interrupt them one by one:
List<Thread> threads = new ArrayList<> ();
for (int n = 1; n <= m; n++) {
Thread t = new HTTP(n + 1, str, j, k);
threads.add(t);
t.start();
}
//later on
for (Thread t : threads) {
t.interrupt();
}
However, it is worth noting a few things:
this will only work if your run method reacts to interruption by stopping what it is doing
you could do the same thing more easily with a thread pool, for example by using one of the ExecutorService returned by the various factory methods provided by the Executors class. They would indeed handle the lifecycle of threads for you.
Firstly, starting 1000 threads is practically pointless as few of them will be scheduled to actually run concurrently.
Secondly, you can't "stop" threads. All you can do is ask them nicely via cooperative code to stop.
The easiest way to do what you want is to shutdown the JVM.

how do I set up the following thread in Java?

I have a thread with the following form:
each execution of each thread is supposed to run a function in the class. That function is completely safe to run by itself. The function returns a value, say an int.
After all threads have been executed, the function values need to be accumulated.
So, it goes (in pseudo-code) something like that:
a = 0
for each i between 1 to N
spawn a thread independently and call the command v = f(i)
when thread finishes, do safely: a = a + v
end
I am not sure how to use Java in that case.
The problem is not creating the thread, I know this can be done using
new Thread() {
public void run() {
...
}
}
the problem is accumulating all the answers.
Thanks for any info.
I would probably do something like:
public class Main {
int a = 0;
int[] values;
int[] results;
public Main() {
// Init values array
results = new int[N];
}
public int doStuff() {
LinkedList<Thread> threads = new LinkedList<Thread>();
for (final int i : values) {
Thread t = new Thread() {
public void run() {
accumulate(foo(i));
}
};
threads.add(t);
t.start();
}
for (Thread t : threads) {
try {
t.join();
} catch (InterruptedException e) {
// Act accordingly, maybe ignore?
}
}
return a;
}
synchronized void accumulate(int v) {
// Synchronized because a += v is actually
// tmp = a + v;
// a = tmp;
// which can cause a race condition AFAIK
a += v;
}
}
Use an ExecutorCompletionService, Executor, and Callable.:
Start with a Callable that calls your int function:
public class MyCallable implements Callable<Integer> {
private final int i;
public MyCallable(int i) {
this.i = i;
}
public Integer call() {
return Integer.valueOf(myFunction(i));
}
}
Create an Executor:
private final Executor executor = Executors.newFixedThreadPool(10);
10 is the maximum number of threads to execute at once.
Then wrap it in an ExecutorCompletionService and submit your jobs:
CompletionService<Integer> compService = new ExecutionCompletionService<Integer>(executor);
// Make sure to track the number of jobs you submit
int jobCount;
for (int i = 0; i < n; i++) {
compService.submit(new MyCallable(i));
jobCount++;
}
// Get the results
int a = 0;
for (int i = 0; i < jobCount; i++) {
a += compService.take().get().intValue();
}
ExecutorCompletionService allows you to pull tasks off of a queue as they complete. This is a little different from joining threads. Although the overall outcome is the same, if you want to update a UI as the threads complete, you won't know what order the threads are going to complete using a join. That last for loop could be like this:
for (int i = 0; i < jobCount; i++) {
a += compService.take().get().intValue();
updateUi(a);
}
And this will update the UI as tasks complete. Using a Thread.join won't necessarily do this since you'll be getting the results in the order that you call the joins, not the order that the threads complete.
Through the use of the executor, this will also allow you to limit the number of simultaneous jobs you're running at a given time so you don't accidentally thread-bomb your system.

Categories

Resources