counter value is not being implemented when threads run - java

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.

Related

I don't get how threads work in this case

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

Invoking synchronized getter and setter

I am trying to practice synchronize keyword with methods.
I wrote the following code:
Adder class:
public class Adder implements Runnable{
Counter counter;
Adder(Counter counter){
this.counter = counter;
}
public void run() {
for (int i=0; i<100; i++)
counter.setCount(counter.getCount()+1);
}
}
Counter class:
public class Counter {
private int count = 0;
public synchronized void setCount(int val){
count = val;
}
public synchronized int getCount(){
return count;
}
}
main:
public class main {
public static void main(String[] args) {
Counter counter = new Counter();
Adder adder = new Adder(counter);
Thread t1 = new Thread(adder);
Thread t2 = new Thread(adder);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(counter.getCount());
}
}
I would expect the output of this to be 200, but it's not deterministic (theoretically, can have any value between 0-200). I suspect the problems is that I am using the getter and setter inline, i.e.
counter.setCount(counter.getCount()+1);
For some reason this "breaks" the mutual exclusion that I am trying to achieve with synchronization, but I can't see why.
I implemented the 1's addition with count++ like so:
public synchronized void add1(){
count++;
}
This worked, maybe because this way I use only one function instead of two inline. Could you explain why the first implementation doesn't work?
Calling the getter and subsequent calling of setter is two independent operations. "Set the result of getter plus one" is not atomic here. So you may perfectly have two gets returning the same value, and two sets of the same value increased by one.
Assume count is 100. You have two threads calls calling the getter, both getting 100. Then they both call the setter, setting 101. So the counter is now 101, not 102 - and both threads "were there" already.
So the result is non-deterministic and depends on the actual order of get/set operations from the two threads.
counter.setCount(counter.getCount()+1); is NOT atomic and it involves 3 steps:
(1) Read the value of count
(2) Add one to count
(3) Write the value of count
In the first approach, you are getting the locks independently i.e., in between the get and set calls of one thread there will be an interference of other threads. So you can't guarantee that the first thread read value is the same as when it comes for the writing.
In the second approach, you are holding the lock and performing all of the above 3 steps, so you will not find any problem.
Also, you can also solve your problem by using the threadsafe AtomicInteger class.

incrementing a static variable thru' 100 different threads without synchronisation, yet getting the final result as 100

I'm incrementing a static variable thru' 100 different threads without synchronisation, yet getting the final result as 100. I've run this code several times and have got same result. Does my code then not require synchronisation? I'm using BlueJ IDE to run the code
public class Main {
private final static int MAX_THREADS = 100;
public static void main(String[] args) {
Thread[] threads = new Thread[MAX_THREADS];
for(int i=0; i<MAX_THREADS; i++) {
threads[i] = new Thread(new Job(), "Thread-" + i);
threads[i].start();
try{
Thread.sleep((int)(Math.random() * 1000));
}catch(InterruptedException e) {
e.printStackTrace();
}
}
for(int i=0; i<MAX_THREADS; i++) {
try {
threads[i].join();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("Final Value: %d\n", Job.getSuccessCount());
}
}
public class Job implements Runnable {
private static int successCount;
public static int getSuccessCount() {return successCount;}
#Override
public void run() {
System.out.printf("%s: Incrementing successCount %d\n", Thread.currentThread().getName(), successCount);
try{
Thread.sleep((int)(Math.random() * 10000));
}catch(InterruptedException e) {
e.printStackTrace();
}
successCount++;
System.out.printf("%s: Incrementing Complete %d\n", Thread.currentThread().getName(), successCount);
}
}
Basically in you code, due to the sleep statements (both in the Thread and by the launcher), you are effectively kicking off the threads allowing for plenty of non busy time to update. That is why it is working. If you code was really multi-threaded, the you would face synchronization issues.
Adding to Wombat's Answer. The final result will always be 100 because you do a Unary Operation after The Sleep in Job class. Basically the read-modify-write commands can run sequentially per Job if the Java Scheduler didn't change the status of the Thread while performing the following.
successCount++
But if you change the Job source code to read-sleep-modify-write then you will definitely see stale value as following.
public class Job implements Runnable {
private static int successCount;
public static int getSuccessCount() {return successCount;}
#Override
public void run() {
System.out.printf("%s: Incrementing successCount %d\n", Thread.currentThread().getName(), successCount);
int sc = successCount; // Read
try{
Thread.sleep((int)(Math.random() * 10000)); // Sleep
}catch(InterruptedException e) {
e.printStackTrace();
}
successCount = sc++; // Modify-Write
System.out.printf("%s: Incrementing Complete %d\n", Thread.currentThread().getName(), successCount);
}
}
With this 2 Threads can read and then sleep and then wake up and write the same value to successCount overwriting the original value.
Your code currently doesn't need synchronization, as no two treads access the same variable at the same time. In other words, only 1 thread in your application is incrementing the variable.
In this case, it is due to the fact that incrementing the variable takes less than Math.random() *1000. Why is it so? Let's observe the threads:
Main Thread:
Launches and starts a thread
Executes both Math.random() and Thread.sleep()
Loops again
While the main thread is doing step 2, the new thread is:
Incrementing variable
Going to sleep
In this case, once the new thread goes to sleep, it just is killed right after, therefore, for our purpose we can regard it as if the thread terminates right after step 1, as it stops affecting the variable (it has no influence on the variable after step 1).
In order for a synchronization problem to occur, two new threads need to access the variable at once. For this to happen, main thread must launch a new thread before the first new thread finishes incrementing. For that to happen, main thread must be faster in: executing Math.random(), Thread.sleep(), and creating a new thread, all before the other thread finishes incrementing. This is obviously not the case, and thus no 2 threads will increment at once, and no synchronization error will occur.
If you do the sums you'll see that you have an average of ten threads running at the same time, all sleeping for an average of five seconds and then doing an increment. So on average the increments won't be closer together than half a second, and the fact their starting is also spaced out by an average of half a second makes that a full second on average. There is essentially no concurrency here at all.

Unexpected output in multithreaded program

class ThreadSafe implements Runnable {
int arr[]=new int[]{1,2,3,4,5};
int sum=0;
public void run() {
int result=sum();
System.out.println("for "+Thread.currentThread().getName()+"the value is"+result);
}
public int sum() {
for(int i=0;i<5;i++) {
sum=sum+arr[i];
System.out.println("calculating sum for thread"+Thread.currentThread().getName()+"sum ="+sum);
try {
Thread.sleep(10);
} catch(Exception e) {}
}
return sum;
}
public static void main(String...d) {
ThreadSafe ts=new ThreadSafe();
ThreadSafe ts1=new ThreadSafe();
Thread t=new Thread(ts);
Thread t1=new Thread(ts1);
t1.start();
t.start();
}
}
I was expecting the output not to come 15. because the sum method is not synchronized so more then one thread can execute the sum method at the same time
What I was expecting that because the 2 thread's will execute the sum method instantly so the output should not be 15 because the first thread will update the value of sum to some value which will be read by the another thread.
So my question is why the output of the program come out the way I'm expecting even though i haven't synchronized the sum() method?
You're creating two instances of ThreadSafe, each with their own sum instance variable.
If you want them to overwrite each other (I'm assuming this is just playing around), create two Threads on the same instance of ThreadSafe. Also, mark your sum variable as volatile to indicate that it can be changed by another thread (to avoid internal caching of the value if the compiler detects that it is not changed elsewhere within the method).
For example, change your main method to this:
public static void main(String...d) {
ThreadSafe ts=new ThreadSafe();
Thread t=new Thread(ts);
Thread t1=new Thread(ts);
t1.start();
t.start();
}
And the beginning of your ThreadSafe class definition to this:
class ThreadSafe implements Runnable {
int arr[]=new int[]{1,2,3,4,5};
volatile int sum=0;
Because you have two instances of ThreadSafe being handled by different threads. For producing your desired result it should be like one instance and multiple threads working on that same instance

Concurrent download counters in Java

As part of our University coursework we have to make a multi threading download server in Java.
Everything is running smoothly apart from one bit : we have to have the server show the total number of downloads for each item each time it is downloaded. So far I have gotten it to work unless both clients request it at the same time. The code is below, If any one has any ides I would be very grateful. Also we must include thread.sleep part and must increment the counter in that convoluted way.
//Snipper from Protocol.java
if (theInput.equals("1")) {
theOutput = "The program displays a message... Another? Y or N";
DownloadCounter counter = new DownloadCounter();
count = DownloadCounter.getcount();//count is a var in Protocol.java it is static
int tmp = count;
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
System.out.println("sleep interrupted");
}
count = tmp + 1;
DownloadCounter.setcount(count);
System.out.println("Download Total " + count);
state = ANOTHER;
The DownloadCounter:
//DownloadCounter.java
public class DownloadCounter {
private static int count;
public static synchronized int getcount(){
return count;
}
public static synchronized void setcount(int num){
DownloadCounter.count = num;
}
}
The fundamental problem is that you have two threads doing a get, increment and set, so consider this situation:
Thread 1: set(5) // now count is 5
Thread 1: get() // Thread 1 gets 5
Thread 2: get() // Thread 2 gets 5
Thread 2: increments its local copy of count to 6
Thread 1: increments its local copy of count to 6
Thread 2: set(6) // now the count is 6
Thread 1: set(6) // the count is still 6, but it should be 7!!!
The solution is to implement an increment method which increments the count in a thread safe manner:
public synchronized void increment()
{
count++;
}
You can also use an AtomicInteger and avoid the locking:
AtomicInteger count = new AtomicInteger(0);
public int getCount()
{
return count.get();
}
public void increment()
{
count.incrementAndGet();
}
You also stated that the counter should count the number of downloads for each item, however, your current code will not do that. Your current counter will count ALL of the downloads for ALL of the items. Hint: you're making everything in DownloadCounter static and that's not going to work well if you want to have a separate counter for each item.
DownloadCounter needs a method for incrementing. There's no safe way to increment the counter with only a getCount and setCount method.
Java has a class AtomicInteger for handling just this type of thing.
Also you are only calling static methods on DownloadCounter, so there is no need to create a new instance.
The key to make it correct is precisely to make the get/increment/set an atomic operation. Instead of the setCount method, there should be a synchronized incrementCount() method.
You could also avoid the synchronization completely by using an AtomicInteger and use its incrementAndGet() method inside the incrementCount() method.
Note that the instruction DownloadCounter counter = new DownloadCounter(); is completely unnecessary. The class should have a private constructor to prevent such unnecessary instantiations.

Categories

Resources