0

Trying this piece of code, I found out that no matter how many times I run the program or iterations are done, race conditions never occur. I know this is not thread safe and I can't understand the reason why this behavior is happening. Any documentation/ideas are welcomed.

Main.java

public class Main {
    static final int N = 1000;
    static int ITERATIONS = 1000000;

    public static void main(String[] args) {
        Thread threads[] = new Thread[10];
        boolean found = true;
        for (int j = 0; j < ITERATIONS; j++) {
            MyThread.val = 0;
            for (int i = 0; i < 10; i++)
                threads[i] = new Thread(new MyThread());
            for (int i = 0; i < 10; i++)
                threads[i].run();
            for (int i = 0; i < 10; i++) {
                try {
                    threads[i].join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if (MyThread.val != N * 10) {
                System.out.println("different !");
                found = false;
            }
        }
        if (found)
            System.out.println("The value is always correct.");
    }
}

MyThread

public class MyThread implements Runnable {
    static int val = 0;

    @Override
    public void run() {
        for (int i = 0; i < Main.N; i++)
            val = val + 1;
    }
}

I tried to run the program for dozens of time, but it always prints "The value is always correct".

(This is not homework or whatever)

Dan Bod
  • 3
  • 1
  • 3
    Try `threads[i].start();` instead of `threads[i].run();` – Gabriel Oct 24 '18 at 17:09
  • Looks to me like everything *is* thread safe because you're calling `join` on all the threads, which means that they will all complete execution before you test the value of `N`. – Yserbius Oct 24 '18 at 17:10
  • @Gabriel This is not the case, per the Java documentation: https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#run() – HackerBoss Oct 24 '18 at 17:14
  • His threads ARE constructed from a separate runnable – HackerBoss Oct 24 '18 at 17:16
  • You don't want to just call the runnable's run method though, you want to start the thread so it's multithreaded. – fgb Oct 24 '18 at 17:19
  • @Dan Bod you aren't using a multithreading in Java when using `threads[i].run()` in this case you using a single thread application. This sample is a not parallel program to simulate a race condition problem - see answer from @Gabriel – e2a Oct 24 '18 at 17:36

3 Answers3

1

You are not actually starting any threads. Calling Thread.run() simply runs the activity of the thread in the current thread. If you were to print start and end timestamps in your method, you might observe this.

Call Thread.start() instead of Thread.run() to observe what you're looking for.

Joe C
  • 15,324
  • 8
  • 38
  • 50
1

Your code has no racing conditions because it runs in a single thread.

The method run simply calls the run method of its Runnable object without creating a new thread. (or does nothing if there is no Runnable object)

The method start actually starts a new thread that runs concurrently.

Docs:

Gabriel
  • 1,922
  • 2
  • 19
  • 37
  • You need to call thread.start() to start a new thread. You also have to call thread.join() to wait until it finished. Your code do not block on calling start() so maybe no thread started to run or maybe they are still running. – Charlie Oct 24 '18 at 17:20
  • @thomas OP's code already calls `join`, the only mistake is calling `run` instead of `start`. – Gabriel Oct 24 '18 at 17:21
  • Yes, that is my fault. Just ignore the comment. – Charlie Oct 24 '18 at 17:22
-1

The race condition will show in the intermediate values, but should not affect the final value. val will always be incremented the same number of times, it will just bounce back-and-forth between threads in incrementing it. If you stored a local val in each thread (with a new class) and incremented it also, you would notice that the local value was updated at a different rate than the global value, and also that this rate could vary substantially as the program ran.

HackerBoss
  • 829
  • 7
  • 16