Concurrent download counters in Java - 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.

Related

Why does wait(100) cause synchronized method to fail in multi threaded?

I am referencing from Baeldung.com. Unfortunately, the article does not explain why this is not a thread safe code. Article
My goal is to understand how to create a thread safe method with the synchronized keyword.
My actual result is: The count value is 1.
package NotSoThreadSafe;
public class CounterNotSoThreadSafe {
private int count = 0;
public int getCount() { return count; }
// synchronized specifies that the method can only be accessed by 1 thread at a time.
public synchronized void increment() throws InterruptedException { int temp = count; wait(100); count = temp + 1; }
}
My expected result is: The count value should be 10 because of:
I created 10 threads in a pool.
I executed Counter.increment() 10 times.
I make sure I only test after the CountDownLatch reached 0.
Therefore, it should be 10. However, if you release the lock of synchronized using Object.wait(100), the method become not thread safe.
package NotSoThreadSafe;
import org.junit.jupiter.api.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static org.junit.jupiter.api.Assertions.assertEquals;
class CounterNotSoThreadSafeTest {
#Test
void incrementConcurrency() throws InterruptedException {
int numberOfThreads = 10;
ExecutorService service = Executors.newFixedThreadPool(numberOfThreads);
CountDownLatch latch = new CountDownLatch(numberOfThreads);
CounterNotSoThreadSafe counter = new CounterNotSoThreadSafe();
for (int i = 0; i < numberOfThreads; i++) {
service.execute(() -> {
try { counter.increment(); } catch (InterruptedException e) { e.printStackTrace(); }
latch.countDown();
});
}
latch.await();
assertEquals(numberOfThreads, counter.getCount());
}
}
This code has both of the classical concurrency problems: a race condition (a semantic problem) and a data race (a memory model related problem).
Object.wait() releases the object's monitor and another thread can enter into the synchronized block/method while the current one is waiting. Obviously, author's intention was to make the method atomic, but Object.wait() breaks the atomicity. As result, if we call .increment() from, let's say, 10 threads simultaneously and each thread calls the method 100_000 times, we get count < 10 * 100_000 almost always, and this isn't what we'd like to. This is a race condition, a logical/semantic problem. We can rephrase the code... Since we release the monitor (this equals to the exit from the synchronized block), the code works as follows (like two separated synchronized parts):
public void increment() {
int temp = incrementPart1();
incrementPart2(temp);
}
private synchronized int incrementPart1() {
int temp = count;
return temp;
}
private synchronized void incrementPart2(int temp) {
count = temp + 1;
}
and, therefore, our increment increments the counter not atomically. Now, let's assume that 1st thread calls incrementPart1, then 2nd one calls incrementPart1, then 2nd one calls incrementPart2, and finally 1st one calls incrementPart2. We did 2 calls of the increment(), but the result is 1, not 2.
Another problem is a data race. There is the Java Memory Model (JMM) described in the Java Language Specification (JLS). JMM introduces a Happens-before (HB) order between actions like volatile memory write/read, Object monitor's operations etc. https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5 HB gives us guaranties that a value written by one thread will be visible by another one. Rules how to get these guaranties are also known as Safe Publication rules. The most common/useful ones are:
Publish the value/reference via a volatile field (https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5), or as the consequence of this rule, via the AtomicX classes
Publish the value/reference through a properly locked field (https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5)
Use the static initializer to do the initializing stores
(http://docs.oracle.com/javase/specs/jls/se11/html/jls-12.html#jls-12.4)
Initialize the value/reference into a final field, which leads to the freeze action (https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.5).
So, to have the counter correctly (as JMM has defined) visible, we must make it volatile
private volatile int count = 0;
or do the read over the same object monitor's synchronization
public synchronized int getCount() { return count; }
I'd say that in practice, on Intel processors, you read the correct value without any of these additional efforts, with just simple plain read, because of TSO (Total Store Ordering) implemented. But on a more relaxed architecture, like ARM, you get the problem. Follow JMM formally to be sure your code is really thread-safe and doesn't contain any data races.
Why int temp = count; wait(100); count = temp + 1; is not thread-safe? One possible flow:
First thread reads count (0), save it in temp for later, and waits, allowing second thread to run (lock released);
second thread reads count (also 0), saved in temp, and waits, eventually allowing first thread to continue;
first thread increments value from temp and saves in count (1);
but second thread still holds the old value of count (0) in temp - eventually it will run and store temp+1 (1) into count, not incrementing its new value.
very simplified, just considering 2 threads
In short: wait() releases the lock allowing other (synchronized) method to run.

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.

Java: Why is my synchronized output still so random

So I'm practicing with synchronization for the first time. I'm trying to implement a practice concept that was described in general on the Oracle Java Concurrency tutorial.
The idea is to have a special Counter object, with methods to increment, decrement, and show value. My goal was to get it run by two different threads to generate random conflicts, and to then solve those conflicts through synchronization. So far I feel like the second part is not working, and I can't figure out what I'm doing wrong.
The code I'm pasting below is simple. There are two threads, with two runnables. Each runnable:
1) contains a reference to the same, single Counter object
2) runs a loop five times
3) sleeps for 1 second each time the loop runs
4) prints the current value of the Counter.
The only difference between MyRunnable1 & MyRunnable2 is that the first one increments the counter, and the second one decrements the counter.
Obviously when I ran it without synchronized methods it produced random results. But even after I synchronized the methods, the results were still apparently random.
SAMPLE RESULTS 1:
1
0
1
0
1
0
-1
0
1
0
SAMPLE RESULTS 2:
-1
0
1
0
1
0
1
0
-1
0
WHAT I THINK IT SHOULD BE: It should consistently go 1 0 1 0 1 0 etc etc until all the loops are finished. If I'm wrong there, if it's the way I'm thinking about thread behavior, please point that out.
Below is my code. All thoughts/advice appreciated. This is my first attempt at using synchronization in any way, I want to get it down because it's such an important concept.
public class CounterSync {
public static void main(String[] args){
Counter c = new Counter();
Thread t1 = new Thread(new MyRunnable1(c));
Thread t2 = new Thread(new MyRunnable2(c));
t1.start();
t2.start();
System.out.println("Done");
}
public static class Counter{
private int c = 0;
public synchronized void increment(){
c++;
}
public synchronized void decrement(){
c--;
}
public synchronized int value(){
return c;
}
}
public static class MyRunnable1 implements Runnable{
private Counter c;
public MyRunnable1(Counter c){
this.c = c;
}
#Override
public void run(){
try{
for(int i = 0; i < 5; i++){
Thread.sleep(1000);
c.increment();
System.out.println(c.value());
}
}catch(InterruptedException ex){
ex.printStackTrace();
}
}
}
public static class MyRunnable2 implements Runnable{
private Counter c;
public MyRunnable2(Counter c){
this.c = c;
}
#Override
public void run(){
try{
for(int i = 0; i < 5; i++){
Thread.sleep(1000);
c.decrement();
System.out.println(c.value());
}
}catch(InterruptedException ex){
ex.printStackTrace();
}
}
}
}
Synchronization does not mean ordering. Perhaps the word 'synchronization' is misleading. In your case, when one has synchronized methods, it means that at a given instant maximum one thread can be running a synchronized method on the object in question.
You can read 'synchronized' as 'one at a time'.
Whenever you have more than one thread running, how much each thread will progress is decided by the system. Further, Thread.sleep is guaranteed to sleep at least for the given interval, but not exact. The two facts combined will give you the random ordering.

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.

Multi-threading program to print numbers from 1 to 50?

im trying to write a program in which two threads are created and the output should be like 1st thread prints 1 and the next thread prints 2 ,1st thread again prints 3 and so on. im a beginner so pls help me clearly. i thought thread share the same memory so they will share the i variable and print accordingly. but in output i get like thread1: 1, thread2 : 1, thread1: 2, thread2 : 2 nd so on. pls help. here is my code
class me extends Thread
{
public int name,i;
public void run()
{
for(i=1;i<=50;i++)
{
System.out.println("Thread" + name + " : " + i);
try
{
sleep(1000);
}
catch(Exception e)
{
System.out.println("some problem");
}
}
}
}
public class he
{
public static void main(String[] args)
{
me a=new me();
me b=new me();
a.name=1;
b.name=2;
a.start();
b.start();
}
}
First off you should read this http://www.oracle.com/technetwork/java/codeconventions-135099.html.
Secondly the class member variables are not shared memory. You need to explicitly pass an object (such as the counter) to both objects, such that it becomes shared. However, this will still not be enough. The shared memory can be cached by the threads so you will have race-conditions. To solve this you will need to use a Lock or use an AtomicInteger
It seems what you want to do is:
Write all numbers from 1 to 50 to System.out
without any number being printed multiple times
with the numbers being printed in order
Have this execution be done by two concurrent threads
First, let's look at what is happening in your code: Each number is printed twice. The reason for this is that i is an instance variable of me, your Thread. So each Thread has its own i, i.e., they do not share the value.
To make the two threads share the same value, we need to pass the same value when constructing me. Now, doing so with the primitive int won't help us much, because by passing an int we are not passing a reference, hence the two threads will still work on independent memory locations.
Let us define a new class, Value which holds the integer for us: (Edit: The same could also be achieved by passing an array int[], which also holds the reference to the memory location of its content)
class Value{
int i = 1;
}
Now, main can instantiate one object of type Value and pass the reference to it to both threads. This way, they can access the same memory location.
class Me extends Thread {
final Value v;
public Me(Value v){
this.v = v;
}
public void run(){
for(; v.i < 50; v.i++){
// ...
}
public static void main(){
Value valueInstance = new Value();
Me a = new Me(valueInstance);
Me b = new Me(valueInstance);
}
}
Now i isn't printed twice each time. However, you'll notice that the behavior is still not as desired. This is because the operations are interleaved: a may read i, let's say, the value is 5. Next, b increments the value of i, and stores the new value. i is now 6. However, a did still read the old value, 5, and will print 5 again, even though b just printed 5.
To solve this, we must lock the instance v, i.e., the object of type Value. Java provides the keyword synchronized, which will hold a lock during the execution of all code inside the synchronized block. However, if you simply put synchronize in your method, you still won't get what you desire. Assuming you write:
public void run(){ synchronized(v) {
for(; v.i < 50; v.i++) {
// ...
}}
Your first thread will acquire the lock, but never release it until the entire loop has been executed (which is when i has the value 50). Hence, you must release the lock somehow when it is safe to do so. Well... the only code in your run method that does not depend on i (and hence does not need to be locking) is sleep, which luckily also is where the thread spends the most time in.
Since everything is in the loop body, a simple synchronized block won't do. We can use Semaphore to acquire a lock. So, we create a Semaphore instance in the main method, and, similar to v, pass it to both threads. We can then acquire and release the lock on the Semaphore to let both threads have the chance to get the resource, while guaranteeing safety.
Here's the code that will do the trick:
public class Me extends Thread {
public int name;
final Value v;
final Semaphore lock;
public Me(Value v, Semaphore lock) {
this.v = v;
this.lock = lock;
}
public void run() {
try {
lock.acquire();
while (v.i <= 50) {
System.out.println("Thread" + name + " : " + v.i);
v.i++;
lock.release();
sleep(100);
lock.acquire();
}
lock.release();
} catch (Exception e) {
System.out.println("some problem");
}
}
public static void main(String[] args) {
Value v = new Value();
Semaphore lock = new Semaphore(1);
Me a = new Me(v, lock);
Me b = new Me(v, lock);
a.name = 1;
b.name = 2;
a.start();
b.start();
}
static class Value {
int i = 1;
}
}
Note: Since we are acquiring the lock at the end of the loop, we must also release it after the loop, or the resource will never be freed. Also, I changed the for-loop to a while loop, because we need to update i before releasing the lock for the first time, or the other thread can again read the same value.
Check the below link for the solution. Using multiple threads we can print the numbers in ascending order
http://cooltekhie.blogspot.in/2017/06/#987628206008590221

Categories

Resources