I'm running this code in Scala:
def injectFunction(body: =>Unit): Thread = {
val t = new Thread {
override def run() = body
}
t
}
private var counter: Int = 0
def increaseCounter(): Unit = this.synchronized {
//putting this as synchronized doesn't work for some reason..
counter = counter + 1
counter
}
def printCounter(): Unit = {
println(counter)
}
val t1: Thread = injectFunction(increaseCounter())
val t2: Thread = injectFunction(increaseCounter())
val t3: Thread = injectFunction(printCounter())
t1.start()
t2.start()
t3.start()
This prints out 1 most of the time, though sometimes 2 and 0 a few times. Shouldn't the this.synchronized before the increaseCounter() method ensure that it's thread safe, and print 2 every time? I've also tried adding this.synchronized in the definition of printCounter(), with no luck.
Very entertaining example! It's so broken that it actually fails at failing to fail:
It was already failing right from the beginning, because it started with the wrong assumption that the synchronized keyword would somehow force the t3 to execute last. But that's simply not the case, the synchronized has nothing to do with the order in which the threads are executed. The threads can still run in arbitrary order, the synchronized merely ensures that they don't enter the synchronized block simultaneously.
Then it additionally fails at generating a random 0 / 1 / 2 output, because there is no synchronized block around the counter in the println, i.e. there is no actual guarantee that the printing thread will see the random changes made by the two other threads. As it is, the printing thread had every right to print 0, without being obliged to do so.
The statements that are executed in the initializer of the object attempt to acquire this in this.synchronized. If one additionally adds tN.join() into the initializer, everything freezes with a deadlock (because the initialization cannot finish before t1, t2, t3 can join, and they cannot join before they can enter a this.synchronized, and they cannot enter this.synchronized before the initialization has unlocked this).
Here is the example that fixes all three problems:
object Example {
def injectFunction(body: =>Unit): Thread = {
val t = new Thread {
override def run() = body
}
t
}
private var counter: Int = 0
def increaseCounter(): Unit = {
//
Thread.sleep(util.Random.nextInt(1000))
this.synchronized {
counter += 1
}
}
def printCounter(): Unit = {
Thread.sleep(util.Random.nextInt(1000))
println("Random state: " + this.synchronized { counter })
}
def main(args: Array[String]): Unit = {
val t1: Thread = injectFunction(increaseCounter())
val t2: Thread = injectFunction(increaseCounter())
val t3: Thread = injectFunction(printCounter())
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
println("Final state: " + counter)
}
}
Now this will indeed randomly output
Random state: 0
Final state: 2
or
Random state: 1
Final state: 2
or
Random state: 2
Final state: 2
The crucial differences to your code are:
random sleeps make the parallelism at least somewhat visible. Without this, you might get 2 & 2 repeatedly.
the reading access to counter in println(counter) must also be synchronized
if you want to demonstrate that the final state of the counter is 2, you have to wait for all three threads to join.
All the statements are in the main, so that the object can be initialized correctly.
Related
I am working on a Enterprise application. I am facing some issues while running application in multithreaded environment. I am writing a program in which there is a variable whose value is getting updated(incremented) at very fast rate (for example 10000 updates/persecond). A loop runs for certain iterations and the value of the variable is incremented and stored in HashMap. Once the loop terminates and value the variable in HashMap is printed. I am getting unexpected value of the variable.
Here is demo program (Please read comments for better understanding) :
class test implements Runnable {
static ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
static AtomicInteger value_to_be_incremented_stored = new AtomicInteger(0); // variable whose value to be updated
static AtomicInteger i = new AtomicInteger(0); // this runs the loop
#Override
public void run() {
for (i.set(0); i.get() < 100000; i.incrementAndGet()) {
/*
This loop should run 100000 times and when loop terminates according to me value of variable
"value_to_be_incremented_stored" should be 100000 as its value is incremented
100000 times the loop also runs 100000 times.
*/
System.out.println("Thread > " + Thread.currentThread() + " " + value_to_be_incremented_stored.incrementAndGet());
map.put("TC", value_to_be_incremented_stored.intValue());
}
System.out.println("Output by Thread " + Thread.currentThread() + " " + map.toString());
}
public static void main(String[] args) {
test t1 = new test();
Thread thread1 = new Thread(t1);
thread1.setName("Thread 1");
Thread thread2 = new Thread(t1);
thread2.setName("Thread 2");
Thread thread3 = new Thread(t1);
thread3.setName("Thread 3");
Thread thread4 = new Thread(t1);
thread4.setName("Thread 4");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
Output (it varies) :
Issue :
I am running loop for 100000 times (i.get() < 100000) then how come value of variable value_to_be_incremented_stored becomes more than 100000.
I found three defects. One there is a race condition in the for loop between the point where you compare the loop counter, and where you increment it. You should do this in one step to get an atomic operation:
for ( ; i.incrementAndGet() < 100000; ) {
The other is there is also a race condition between the increment of your counter, and placing it in the map. Even though you increment these in series, any thread could be have a different value internally (it's at a different point in the loop) and it could put a previous value in the global map. You need atomicity here to to make sure the value you increment is the value you place in the loop.
synchronized( lock ) {
value_to_be_incremented_stored.incrementAndGet();
map.put("TC", value_to_be_incremented_stored.intValue());
}
Finally for some reason the < comparison produces a value of 99999 for me. I had to use <= to fix it.
(And as we discussed in the comments, setting i.set(0) at the start of each for loop doesn't work for fairly obvious reasons. Four defects, I guess.)
class ThreadTestX implements Runnable {
static ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
static AtomicInteger value_to_be_incremented_stored = new AtomicInteger(0); // variable whose value to be updated
static AtomicInteger i = new AtomicInteger(0); // this runs the loop
static final Object lock = new Object();
#Override
public void run() {
for ( ; i.incrementAndGet() <= 100000; ) {
/*
This loop should run 100000 times and when loop terminates according to me value of variable
"value_to_be_incremented_stored" should be 100000 as its value is incremented
100000 times the loop also runs 100000 times.
*/
synchronized( lock ) {
value_to_be_incremented_stored.incrementAndGet();
// System.out.println("Thread > " + Thread.currentThread() +
// " " + value_to_be_incremented_stored.get());
map.put("TC", value_to_be_incremented_stored.intValue());
}
}
System.out.println("Output by Thread " + Thread.currentThread()
+ " " + map.toString());
}
public static void main(String[] args) {
ThreadTestX t1 = new ThreadTestX();
Thread thread1 = new Thread(t1);
thread1.setName("Thread 1");
Thread thread2 = new Thread(t1);
thread2.setName("Thread 2");
Thread thread3 = new Thread(t1);
thread3.setName("Thread 3");
Thread thread4 = new Thread(t1);
thread4.setName("Thread 4");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
Output:
run:
Output by Thread Thread[Thread 4,5,main] {TC=100000}
Output by Thread Thread[Thread 3,5,main] {TC=100000}
Output by Thread Thread[Thread 1,5,main] {TC=100000}
Output by Thread Thread[Thread 2,5,main] {TC=100000}
BUILD SUCCESSFUL (total time: 0 seconds)
Afterthoughts: And in spite of getting marked correct, I'm not sure I was correct. The problem here is that you are trying to keep three things in sync: the loop counter i, the value to be incremented, and the map. Allowing any of these to be executed outside of a synchronized block may invite them to be in an unexpected state. I think the following may be safer:
#Override
public void run() {
for ( ;; ) {
synchronized( lock ) {
if( i.incrementAndGet() <= 100000 ) {
value_to_be_incremented_stored.incrementAndGet();
map.put("TC", value_to_be_incremented_stored.intValue());
}
else
break;
}
}
System.out.println("Output by Thread " + Thread.currentThread()
+ " " + map.toString());
}
This removes the need for declaring the variables as AtomicInteger, but I don't see how else you ensure that their values don't change (due to some other thread) as that loop executes.
Your "demo program" suffers from two simultaneous defects.
Defect #1 is the i.set( 0 ) pointed out by tsolakp. You say you fixed that but you are still getting a value of more than 100000. I also tried it and indeed, the final value is still larger than 100000.
I modified the program to be able to create an arbitrary number of threads, and I tried with 3, 10, and 20 threads. I got a final number of 100003, 100009, and 100019 respectively. See a pattern? So:
Defect #2 is that on the last iteration, when the value of i is 99999, the expression i.get() < 100000 is true for all threads, so all threads proceed to execute once more. The i.incrementAndGet() clause is visually sitting right next to i.get() < 1000000; but it does not get executed until the end of the loop.
So, all threads get a chance to increment i once more after the last iteration.
Everytime a new thread enters the run method it will reset your i count to zero via the first statement in the for loop by calling i.set(0).
Update: Next step after fixing reset issue, is to step through the code and see how the threads will behave.
Lets say three threads get inside the for loop while the fourth thread increments i. What will happen is that value_to_be_incremented_stored will increment 3 times and i only one time.
In the code below:
I am updating num[1]=0 of an AtomicIntegerArray num 1000 times each in 2 threads.
At the end of the 2 threads in main thread ;shouldn't the value of num[1] be 2000 as there shouldn't be data races in an AtomicIntegerArray .
However I get random values < 2000. Could someone tell me why?
Code:
import java.util.concurrent.atomic.AtomicIntegerArray;
public class AtomicIntegerArr {
private static AtomicIntegerArray num= new AtomicIntegerArray(2);
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new MyRun1());
Thread t2 = new Thread(new MyRun2());
num.set(0, 10);
num.set(1, 0);
System.out.println("In Main num before:"+num.get(1));
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("In Main num after:"+num.get(1));
}
static class MyRun1 implements Runnable {
public void run() {
for (int i = 0; i < 1000; i++) {
num.set(1,num.get(1)+1);
}
}
}
static class MyRun2 implements Runnable {
public void run() {
for (int i = 0; i < 1000; i++) {
num.set(1,num.get(1)+1);
}
}
}
}
Edit: Adding num.compareAndSet(1, num.get(1), num.get(1)+1); instead of num.set(1,num.get(1)+1); doesnt work either.
I get random values < 2000. Could someone tell me why?
This is called the lost-update problem.
Because, in the following code:
num.set(1, num.get(1) + 1);
Although each individual operation involved is atomic, the combined operation is not. The single operations from the two threads can interleave, causing updates from one thread to be overwritten with stale value by another thread.
You can use compareAndSet to solve this problem, but you have to check whether the operation is successful, and do it again when it fails.
int v;
do {
v = num.get(1);
} while (!num.compareAndSet(1, v, v+1));
There's also a method for exactly this purpose:
num.accumulateAndGet(1, 1, (x, d)->x+d);
accumulateAndGet(int i, int x, IntBinaryOperator accumulatorFunction)
Atomically updates the element at index i with the results of applying the given function to the current and given values, returning the updated value. The function should be side-effect-free, since it may be re-applied when attempted updates fail due to contention among threads. The function is applied with the current value at index i as its first argument, and the given update as the second argument.
This is a classic race condition. Any time you have a fetch, an operation, and a put, your code is racy.
Consider two threads, both executing num.set(1,num.get(1)+1) at roughly the "same time." First, let's break down what the expression itself is doing:
it fetches num.get(1); let's call this x
it adds 1 to that; let's call this y
it puts that sum in at `num.set(1, y);
Even though the intermediate values in your expression are just values on the stack, and not explicit variables, the operation is the same: get, add, put.
Okay, so back to our two threads. What if the operations are ordered like this?
inital state: n[1] = 5
Thread A | Thread B
========================
x = n[1] = 5 |
| x = n[1] = 5
| y = 5 + 1 = 6
y = 5 + 1 = 6 |
n[1] = 6 |
| n[1] = 6
Since both threads fetched the value before either thread put its added value, they both do the same thing. You have 5 + 1 twice, and the result is 6, not 7!
What you want is getAndIncrement(int idx), or one of the similar methods that does the get, adding, and putting atomically.
These methods can actually all be built on top of the compareAndSet method you identified. But to do that, you need to do the increment within a loop, trying until the compareAndSet returns true. Also, for that to work, you have store that initial num.get(1) value in a local variable, rather than fetching it a second time. In effect, this loop says "keep trying the get-add-put logic until it works without anyone else having raced between the operations." In my example above, Thread B would have noticed that compareAndSet(1, 5, 6) fails (since the actual value at that time is 6, not 5 as expected), and thus retried. This is in fact what all of those atomic methods, like getAndIncrement, do.
Alright folks.. I'm back again (seems to be my home lately).
I'm going through the whole cave of programming YouTube vids on multi-threading. This particular one uses 2 threads that go through a for loop which adds 1 to a variable 10,000 times each. So you join them so the result is 20,000 when it's done.
public class main {
private int count = 0;
public static void main(String[] args) {
main main = new main();
main.doWork();
}
public void doWork(){
Thread t1 = new Thread(new Runnable(){
public void run(){
for (int i = 0; i < 10000; i++){
count++;
}
}
});
Thread t2 = new Thread(new Runnable(){
public void run(){
for (int i = 0; i < 10000; i++){
count++;
}
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException ex) {
Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Count is: " + count);
}
}
Thing is.. when i change the iterations:
i < 10 = 20 (correct)
i < 100 = 200 (correct)
i < 1000 = 2000 (correct)
i < 10000 = 13034 (first run)
= 14516 (second run)
= ... etc..
Why won't it properly handle iterations in the tens of thousands?
You have demonstrated the classic race condition, which occurs when 2 or more threads are reading and writing to the same variable in conflicting ways. This arises because the ++ operator isn't an atomic operation -- multiple operations are occurring, and a thread could be interrupted in between operations, e.g.:
Thread t1 reads count (0), and calculates the incremented value (1), but it hasn't stored the value back to count yet.
Thread t2 reads count (still 0), and calculates the incremented value (1), but it hasn't stored the value back to count yet.
Thread t1 stores its 1 value back to count.
Thread t2 stores its 1 value back to count.
Two updates have occurred, but the net result is only an increase of 1. The set of operations which must not be interrupted is a critical section.
This appears to have happened 20,000 - 13,034 times, or 6,966 times in your first execution. You may have gotten lucky with lower bounds, but regardless of the magnitude of the bounds, the race condition can happen.
In Java, there are several solutions:
Place synchronized blocks around the critical sections (both count++ lines), locking on this.
Change count to an AtomicInteger, which encapsulates such operations atomically on its own. The getAndIncrement method would replace the ++ operator here.
and this a normal thread program
class Counter implements Runnable {
private int currentValue;
public Counter() { currentValue = 0; }
public int getValue() { return currentValue; }
public void run() { // (1) Thread entry point
try {
while (currentValue < 5) {
System.out.println(Thread.currentThread().getName() + ": " + (currentValue++)); // (2) Print thread name.
Thread.sleep(250); // (3) Current thread sleeps.
}
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + " interrupted.");
}
System.out.println("Exit from thread: " + Thread.currentThread().getName());
}
}
//_______________________________________________________________________________
public class Client {
public static void main(String[] args) {
Counter counterA = new Counter(); // (4) Create a counter.
Thread worker = new Thread(counterA, "Counter A");// (5) Create a new thread.
System.out.println(worker);
worker.start(); // (6) Start the thread.
try {
int val;
do {
val = counterA.getValue(); // (7) Access the counter value.
System.out.println("Counter value read by " + Thread.currentThread().getName()+ ": " + val); // (8) Print thread name.
Thread.sleep(1000); // (9) Current thread sleeps.
} while (val < 5);
} catch (InterruptedException e) {
System.out.println("The main thread is interrupted.");
}
System.out.println("Exit from main() method.");
}
}
and the output is
Thread[Counter A,5,main]
Counter value read by main thread: 0
Counter A: 0
Counter A: 1
Counter A: 2
Counter A: 3
Counter value read by main thread: 4
Counter A: 4
Exit from thread: Counter A
Counter value read by main thread: 5
Exit from main() method.
My question is even though the worker thread was started initially before the Main thread enters it's try block, Main thread execution starts first and then when the Main thread goes to sleep child thread gets into action.
As this picture(taken from "A Programmer's Guide To Java SCJP Certification : A Comprehensive Primer 3rd Edition"
Author: Khalid A Mughal, Rolf W Rasmussen) depicts that when the start method is called on the thread it returns immediately.
Please explain this point that why on invoking start method it return immediately and does the thread get starts on calling the start method. As here on calling the start method it doesn't invoke run method of the class. So when does actually the thread starts ?
Also explain this " the call to the start() method is asynchronous."
there are three things that you are missing in your overall analysis.
Call to thread's start method is sequential not parallel. Its the call to run method of Thread that is concurrent. So if you have 5 statements in main method that call start, the 5ht is not going t be called first. Thats the 'happens before' guarantee that JVM specs give you. However the run method of 1 first may get called before or after the call to the second start statement. This depends as its more of a CPU time slicing issue rather than program execution.
When more than 1 thread runs in your program the order of output is in-deterministic. That's because they run in parallel. You can never be sure that the same program will run in same order on two machines or even in two runs on the same machine. In your question you have posted only 1 output. Run the program like 20 times one after another and match the output. I am sure 2 or 3 would be entirely different.
Finally, you are basing your analysis on the order or execution of your concurrent code. That's the biggest blooper programmer make. Concurrent programs are never intended to run in a specific order or sequence. Just try to make your Runnable work an atomic mutually exclusive task (mutually exclusive to the rest of program or even to other Runnables) and track its own execution. Dont mix Threads together.
You cannot directly enforce which Thread is executed/running when. Once you start it, it's handled on lower level(usually by OS) and the results may differ on different machine or even in different execution. If you need more control, you need to use some synchronization mechanism.
The thread is isn't started synchronously underneath the call to start(). It happens later (asynchronously). In other words, just because you called start() doesn't mean the thread has started.
They why and how are all implementation details, that may depend on JVM and/or OS implementations.
While running each thread why does the countdown.getCount() always print '3' even after the previous thread has already called countdown.countDown() and reduced the Latch Count by 1?
I am kind of worndering how Java knows that the Latch Count has reached 0, so that it can release all the 3 threads.
import java.util.concurrent.CountDownLatch;
class b {
static final CountDownLatch countdown = new CountDownLatch(3);
public static void main(String[] args) {
for (int i = 0; i < 3; ++i) {
Thread t = new Thread() {
public void run() {
System.out.printf("Starting on %d other threads.\n",
countdown.getCount());
countdown.countDown();
System.out.printf("new on %d other threads.\n",
countdown.getCount());
try {
countdown.await(); // waits until everyone reaches this
// point
// System.out.println("Go again : "
// +countdown.getCount());
} catch (Exception e) {
}
}
};
t.start();
}
System.out.println("Go");
}
}
you are starting 3 threads in parallel. depending on how fast they start, they could all print "3" before any of the threads manages to call countDown() (at least for the "Starting on..." line). the "new on ..." line, however, should print out some range of numbers between 2 and 0.
It's absolutely possible that all three threads print "Starting on 3.." as the threads run in parallel, and the count doesn't change until a thread executed countDown(). To really understand what's going on, I suggest you prepend System.nanoTime() and thread name before your print statements as below:
...
Thread t = new Thread("Thread-" + i) {
...
System.out.printf("%d> %s: Starting on %d other threads.\n", System.nanoTime(), getName(), countdown.getCount());
countdown.countDown();
System.out.printf("%d> %s: new on %d other threads.\n", System.nanoTime(), getName(), countdown.getCount());
Sometimes you'd get an output like below which may give you the impression that Thread-2 is disregarding Thread-1's call to countDown:
1407489646569321000> Thread-0: Starting on 3 other threads.
1407489646569324000> Thread-1: Starting on 3 other threads.
1407489646602463000> Thread-1: new on 1 other threads.
1407489646569513000> Thread-2: Starting on 3 other threads.
1407489646602107000> Thread-0: new on 2 other threads.
1407489646603275000> Thread-2: new on 0 other threads.
However, that is not the case, and we can verify the correct order of operations by looking at the timestamp. The mixup in the output is due to inherent unpredictability in thread scheduling, depending on which thread gets the cpu splice.
Having said that, they may not always print 3, depending on thread scheduling or delays. As an example, try putting a Thread.sleep(..) as shown below:
public static void main(String[] args) throws Exception {
for (int i = 0; i < 3; ++i) {
Thread t = new Thread() {
public void run() {
/* As before */
}
};
t.start();
Thread.sleep(100); // Artificial Delay
}
}
Now you should see different results like below:!
1407490223575404000> Thread-0: Starting on 3 other threads.
1407490223607879000> Thread-0: new on 2 other threads.
1407490223676233000> Thread-1: Starting on 2 other threads.
1407490223676818000> Thread-1: new on 1 other threads.
1407490223777623000> Thread-2: Starting on 1 other threads.
1407490223778221000> Thread-2: new on 0 other threads.
Internally, the CountDownLatch maintains a first in, first out wait Queue (See. AbstractQueuedSynchronizer). The value of the count is synchronized, and the waiting threads are only released when the count becomes 0 or someother thread interrupts the waiting thread. This is the mechanism used by the latch to keep track of when all the threads have arrived at the latch.
If you're interested in understanding the latch in the context of testing, checkout http://razshahriar.com/2014/08/testing-asynchronous-code-in-java-with-countdownlatch/
Hope this helps clarify your investigation of the Program behaviour.