I don't get how threads work in this case - java

The following code is shows how no race condition in thread works, but I don't get the difference between with the synchronized and without it. I thought the static variable counter will be added to 20000 anyway but it turned out that without synchronized counter would be less than 20000. Can you please explain how threads work in this case? Also, in Java, are threads are actually not running "concurrently", instead are they taking turns to run for a while?
public class NoRaceCondition implements Runnable {
private static int counter = 0;
private static Object gateKeeper = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(new NoRaceCondition());
Thread t2 = new Thread(new NoRaceCondition());
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) { e.printStackTrace(); }
System.out.printf("counter = %d\n", counter);
}
public void run() {
synchronized (gateKeeper) {
for (int i = 0; i < 10000; i++) {
{
counter++;
}
}
}
}
}

You can think of count++ as 3 separate steps.
read the value of count
increment the value
override count with the new incremented value
When multiple thread execute the above steps concurrently, race conditions may occur. 1 example of race condition is
Let count = 1
Let there be 2 threads named A and B
Thread A reads the value of count and get 1
Thread B reads the value of count and get 1
Thread A increments its value and get 2
Thread B increments its value and get 2
Thread A writes the value to count
count is now 2
Thread B writes the value to count
count is now 2 again when it's expected to be 3 after 2 increments

Related

Using join() method to wait for the thread execution to complete but not getting the desired result [duplicate]

This question already has answers here:
Java volatile keyword not working as expected
(6 answers)
Closed 14 days ago.
Created 2 threads and called the join() method on them. I was expecting the threads would run sequentially and give the desired result, but I am getting some random values in the result.
public class TestJoinMethod {
volatile private int count =0;
public static void main(String[] args) {
TestJoinMethod testJoinMethod = new TestJoinMethod();
testJoinMethod.execute();
}
public void execute() {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
for(int i=0; i<10000; i++) {
count++;
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
for(int i=0; i<10000; i++) {
count++;
}
}
});
t1.start();
t2.start();
try {
t1.join();
System.out.println(count);
t2.join();
System.out.println(count);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
Using the above code to get the value of count variable. As per my understanding the join() method waits for the thread execution to be completed before the control of the calling thread goes to next statement. Expected result : sysout statement should print 10000 , 200000 respectively. However, the result is giving some random values : 14125 , 14125 or 16911, 16911.
Not able to understand why is this happening here, went through some tutorials also, but couldn't understand the exact issue here.
Appreciate your help here.
So let's think about the sequence that happens here. This part:
t1.start();
t2.start();
Starts the two threads running, concurrently with each other. We haven't executed a join() yet, just started the two threads, so they're both running.
try {
t1.join();
System.out.println(count);
Then we get to this join(). Both t1 and t2 have been running for a while at this point. Finally, t1 finishes and then we print out count. But t2 has also been running, so we expect count to have been incremented more than it would have been by t1 alone.
Then we get to this:
t2.join();
System.out.println(count);
This does pretty much the same thing: wait for t2 to finish, then print out count again.
It's essentially impossible to predict how much of the execution of t1 and t2 may overlap with each other though. Maybe a lot, but maybe almost none at all.
Worse, you haven't done anything to protect access to count, you're getting a data race. The result is, in a word, garbage.
To get the result you're apparently looking for, you'd have prevent concurrent access of your threads though (in other words, render the use of threads utterly useless). The obvious way to do that would be something like:
t1.start();
t1.join();
System.out.println(count);
t2.start();
t2.join();
System.out.println(count);
This should produce the result you desire--but it's equivalent to just running all the code in one thread, so there's no real point to any of it.
The compiler already is warning you that
Non-atomic operation on volatile field 'count'
The threads can randomly read the same value and update it at the same time, which will result in the same number. For example:
Thread 1 reads count = 0
Thread 2 reads count = 0
Thread 1 does 0+1
Thread 1 updates count = 1
Thread 2 does 0+1
Thread 2 updates count = 1
This can be solved synchronizing the access to the count variable, for example using AtomicInteger:
private final AtomicInteger count = new AtomicInteger(0);
count.getAndIncrement();
Also note that the final result will be 20000 for both threads, you're incrementing the same counter.

Problem with thread synchronizing in Java

I'm well aware that this might be considered a duplicate, however I ran through many answers considering my problem here I can't come up with a solution.
I synchronized my runnable with an object shared by multiple threads and explicitly synchronized the method I am using inside, but the outcome of the program is always 3000.
I tried locking the Counter class but it won't change a thing.
Could anyone explain me why none of my actions work in this particular example?
public static void zad3() {
var counter = new Counter();
var toRun = new Runnable() {
#Override
public void run() {
synchronized (counter) {
for (var i = 0; i < 1000; i++) {
counter.add(1);
}
}
}
};
var t1 = new Thread(toRun);
var t2 = new Thread(toRun);
var t3 = new Thread(toRun);
t1.start();
t2.start();
t3.start();
try {
t1.join();
t2.join();
t3.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("counter = " + counter.getCount());
}
public class Counter {
protected long count_ = 0;
public synchronized void add(long value) {
count_ += value;
}
public long getCount() {
return count_;
}
}
edit:
As suggested the problem was in the loop being constantly ran a 1000 times by each of the threads.
My solution:
var toRun = new Runnable() {
#Override
public void run() {
synchronized (counter) {
for (var i = counter.getCount(); i < 1000; i++) {
counter.add(1);
}
}
}
};
Well you have synchronized the complete for loop around the "counter" variable which means that each thread will run tthe block once. 3 X 1000 = 3000
this block will be executed once per thread
for (var i = 0; i < 1000; i++) {
counter.add(1);
}
UPDATE: judging from your comments that you want interrupt on 1000 example code can be:
t1.start();
t2.start();
t3.start();
while(counter.getValue()<1000) {
Thread.sleep(20)
}
Annother suggestion:
public class Incremetor extends Runnable {
Counter counter;
public Incremetor(Counter counter) {
this.counter = counter;
}
public void run() {
counter.increment();
}
}
ExecutorService executorService = Executors.newFixedThreadPool(8); // this mean 8 threads in total to do your runnables.
for (int i=0;i<1000;++i) {
executorService.submit(new Incrementor(counter));
}
So the problem is that you let each thread attempt 1000 increments, so you'll need something like this instead:
while (counter.getCount() < 1000) {
counter.add(1);
}
The solution you have provided may give you the correct result, but you're actually only incrementing the counter from 1 thread. When you make a synchronized block with synchronized(object) { }, all threads will attempt to get the lock for this block, but only one will. That means in your solution, that the first thread which gets the lock, will do all 1000 increments. When the thread releases the lock and lets the others get it, the work is already done. A solution that actually distributes the increments amongst the 3 threads, should therefore not synchronize the entire for-loop.
If you run the while-loop I suggested, you will get a lot closer to 1000, but it may actually be more than 1000. Remember to run your program 10 times or set up a test-function which runs it 100 times and reports back. The problem, is that from the point of reading counter.getCount(), the value may already have changed by another thread. To reliably always get 1000, you could ensure exclusive rights to both reading and writing to the counter:
while (true) {
synchronized (counter) {
if (counter.getCount() < 1000) {
counter.add(1);
} else {
break;
}
}
}
Notice that incrementing one variable like this, is slow. You're only doing 1000, but try with one billion. In fact, the 3-threaded version takes (on my PC) 1m17s, whereas a simple sequential loop takes ~1.2 seconds. You can solve this by splitting the workload amongst the threads and letting them work on a local counter with exclusive rights and then finally add the results.

Java Multi Threading / initiating threads in a loop

Can someone help me to solve this multi-threading problem ?
The program should initiate three threads with a common resource. Each thread should print a incremented count value. Sample output is mentioned below. where T1,T2 and T3 are threads.
T1 T2 T3
1 2 3
4 5 6
7 8 9
My current code:
public class RunnableSample implements Runnable {
static int count = 0;
public void run() {
synchronized (this) {
count++;
System.out.println(
"Current thread : Thread name :" + Thread.currentThread().getName()
+ " Counter value :" + count
);
}
}
}
//main method with for loop for switching between the threads
public class ThreadInitiator {
public static void main(String[] args) {
RunnableSample runnableSample = new RunnableSample();
Thread thread1 = new Thread(runnableSample, "T1");
Thread thread2 = new Thread(runnableSample, "T2");
Thread thread3 = new Thread(runnableSample, "T3");
for (int i = 0; i < 9; i++) {
thread1.start();
thread2.start();
thread3.start();
}
}
}
Create a synchronized method to increment the value. When a method is identified as synchronized, only one thread can access it at a time and the other threads wait for the initial thread to complete method execution before they can access the method.
Pls check How to synchronize a static variable among threads running different instances of a class in java?

Printing numbers in loop with two threads

I am trying out codes with multiple threads.
Below is my code:
package com.thread.practice;
public class ThreadPratice1 {
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
Thread t1 = new Thread(r, "Thread 1");
Thread t2 = new Thread(r, "Thread 2");
t1.start();
t2.start();
}
}
package com.thread.practice;
public class MyRunnable implements Runnable {
private static int i = 0;
#Override
public void run() {
for(i = 0; i <10;i++){
System.out.println("Thread: "+ Thread.currentThread().getName()
+" value of i: "+i);
try {
//System.out.println("Thread: "+ i);
Thread.sleep(1000);
//System.out.println("inside runnable: "+Thread.currentThread().getState());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
But in the output it is always printing the value of i as 0 twice in the beginning.
Output is coming kind of like this:
Thread: Thread 1 value of i: 0
Thread: Thread 2 value of i: 0
Thread: Thread 1 value of i: 2
Thread: Thread 2 value of i: 2
Thread: Thread 1 value of i: 3
Thread: Thread 2 value of i: 4
Thread: Thread 1 value of i: 5
Thread: Thread 2 value of i: 6
Thread: Thread 1 value of i: 7
Thread: Thread 2 value of i: 8
Thread: Thread 1 value of i: 9
May someone please help me in understanding this issue?
Because the value of i at the begging of the execution of the two threads is 0.
In other words, thread one and thread two stared almost at the same time, so the two of them set the i to 0 for the first loop.
for(i = 0; i <10;i++) {
Then the value changes between thread because you made i static. so it will be shared between your two threads.
You made "i" static, which means it will be the same over all threads and objects. Take away the static modifier and your code will work properly.
edit: I misinterpreted what you asked- don't set i to 0 in the for loop, it will look something like this:
for(;i<10;i++) { /*mycode*/}
One of these two is probably what you want anyway, your question was a little bit vague
value of i is incremented by the for loop only after the loop is executed. Execution of for loop takes a finite amount of time. Since you are starting the threads together (almost), both the threads may or may not print i after the other thread has finished one loop. Since you are not doing to ensure thread safety, the result will be unpredictable like the one you got.
First, You shouldn't use the primitive int type for concurrency, it's not thread safe and it maybe will cause Race Condition,
and try to use AtomicInteger to replace int, it's thread safe. the example maybe:
public class ThreadPratice1 {
public static void main(String[] args) {
AtomicInteger number = new AtomicInteger(0);
MyRunnable r = new MyRunnable(number);
Thread t1 = new Thread(r, "Thread 1");
Thread t2 = new Thread(r, "Thread 2");
t1.start();
t2.start();
}
}
class MyRunnable implements Runnable {
private AtomicInteger number;
public MyRunnable(AtomicInteger number) {
this.number = number;
}
#Override
public void run() {
while (number.get() < 10) {
System.out.println("Thread: " + Thread.currentThread().getName()
+ " value of i: " + number.getAndIncrement());
}
}
}

counter value is not being implemented when threads run

I've created the following program which runs two threads with the same thread instance. I've initialised a counter and when each of the thread runs, the counter value should be implemented and at the end it should output in console.
public class MTThread {
static int count = 0;
public static void main(String arg[]){
System.out.println("Main started");
MTThreadInner in1= new MTThreadInner(1,count);
MTThreadInner in2= new MTThreadInner(2,count);
in1.start();
in2.start();
while (true) {
try {
in1.join();
in2.join();
break;
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Main finished, count = :"+ count);
}}
class MTThreadInner extends Thread {
int num; int counter;
MTThreadInner(int i,int z) {
counter=z;
num = i;
}
public void run(){
// TODO Auto-generated constructor stub
yield();
System.out.println("This ran Thread "+ num);
counter=counter+1;
}
}
However the output always shows count as "0":
Main started
This ran Thread 1
This ran Thread 2
Main finished, count = :0
The output should be count = 0 as you don't change this variable anywhere.
What you do is copy this variable to another field in MTThreadInner.counter where each thread changes it's own copy to 1 but this is an entirely unrelated variable.
What you might have expected to do is to increment a shared, thread safe variable. To do this I suggest making count an AtomicInteger
static AtomicInteger count = new AtomicInteger(0);
This way you can copy the reference to the same shared, thread safe object and when you call counter.incrementAndGet() in each thread it will increment this object.
I have created the following program which runs two threads with the same thread instance.
No, you have created a program that runs two threads via different instances of the same Thread subclass.
The counter value should be implemented and at the at end it should output in console.
Each instance of your Thread subclass has a private counter variable, which I'm sure those threads do update (but how could you tell?). That's unrelated to the static variable MTThread.count, which is what you print at the end.

Categories

Resources