I am trying Java multi threaded counter. I first tried without any synchronisation to observe the race condition. But my counter is not incremented by worker threads.
Code - MAIN METHOD
public static void main(String... args) {
System.out.println("Program started");
Integer sum = 0;
System.out.println("Initial Sum : " + sum);
for (int i = 0; i < 100; i++) {
WorkerThread workerThread = new WorkerThread(sum, i);
workerThread.run();
}
System.out.println("Final Sum : " + sum);
}
Code - WorkerThread class
public class WorkerThread implements Runnable {
private Integer localSum;
public WorkerThread(Integer sum, int i){
localSum = sum;
System.out.println(localSum);
}
#Override
public void run() {
localSum += 1;
}
}
I wonder why incrementing localSum does not affect to Integer wrapper object sum.
The sum value stays at 0. Can anyone help me to figure out how to pass Integer wrapper into a thread and increment the original value?
The problem is that localSum += 1 does not do what you think it does.
Integer objects are immutable: You can not change the value of an Integer. The localSum+=1 statement creates a new Integer instance, and it changes the localSum variable to refer to the new instance. Meanwhile, the main() routine's sum variable always will refer to the original, immutable instance.
#Murat Karagöz said, "Use an AtomicInteger." That would solve two problems;
AtomicInteger instances are mutable, and
The ai.incrementAndGet() operation, and other AtomicInteger operations are thread safe.
Your program, as written, doesn't need thread safety, but it will need once you change it to actually create multiple threads.
It will help you to get it right if you make all of your AtomicInteger variables final. E.g.;
public class WorkerThread implements Runnable {
private final AtomicInteger localSum;
public WorkerThread(AtomicInteger sum, int i){
localSum = sum;
System.out.println(localSum.get());
}
...
}
You don't want to accidentally change the value of the localSum field (i.e., you don't want to change which AtomicInteger instance it points to,) You want to mutate the AtomicInteger instance itself.
Related
I have a problem where i have to print the numbers in such format.
First 1
First 2
Second 3
Second 4
First 5
First 6
Second 7
Second 8
First 9
and so on...
I have implemented my runnable interface as below.
class ThreadDemo implements Runnable {
public volatile Integer num;
public Object lock;
public ThreadDemo(Integer num, Object lock) {
this.num = num;
this.lock = lock;
}
#Override
public void run() {
try {
while (true) {
int count = 0;
synchronized(lock) {
Thread.sleep(100);
while (count < 2) {
System.out.println(Thread.currentThread().getName() + " " + num++);
count++;
}
lock.notify();
lock.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
My main class is as follows
public class CoWorkingThreads {
private static volatile Integer num = new Integer(1);
public static void main(String...args) {
Object lock = new Object();
Thread thread1 = new Thread(new ThreadDemo(num, lock), "First");
thread1.start();
Thread thread2 = new Thread(new ThreadDemo(num, lock), "Second");
thread2.start();
}
}
when i run the program i am getting the output as follows
First 1
First 2
Second 1
Second 2
First 3
First 4
Second 3
Second 4
Instead of previously expected results. But when I Change the integer to atomic integer type i start getting the expected result. can anyone explain what is i can do to make it run with integer instead of using atomic integer
Java Integer cannot be passed by reference. On your code, each thread will create a copy of the variable. However atomicInteger can be passed by reference.
Also, to get the correct result, you can change the num variable to static variable.
public static Integer num = 1;
public Object lock;
public ThreadDemo(Integer num, Object lock) {
//this.num = num;
this.lock =lock;
}
Your problem is that the Integer class is Immutable, so you cannot use it in separate threads to reference a shared value. Answer: Create your own, Mutable, Integer class.
You can find a similar question answered on SO here
Just for your knowledge, instead of using a synchronized block, on an Object, you might want to experiment with Lock(s) (e.g. ReentrantLock) and their associated Condition(s).
Using Condition(s) you can manage your shared resources in a mutually exclusive way between threads.
I still believe that this question is NOT answered correctly. The flaw here is that you have never marked shared data as static. So each thread has it's own copy independent of the other. Integer is an immutable wrapper class, which is true but it has nothing to do in this context. Let's dig more into num++. The ++ operator applies only to (primitive) integer types. Behind the scenes, num is unboxed, the ++ is applied, and the result is then assigned back to num (after a boxing conversion). The Integer class does not have a ++ operator. In fact, Integer objects are immutable.
Immutable means every time you increment and create a new value object. And that new value object is assigned back to your num reference. But two threads have their own copy of num reference pointing to different Integer boxed primitives. So they increment it independently of one another which is not visible to the other. If you want to share it between threads you have to use static access modifier at the site of declaration. More over a passing two values to a shared variable does not make sense. Instead you can initialize it inline. Here's the fixed version.
public class ThreadDemo implements Runnable {
public static Integer num = 1;
public static final Object lock = new Object();
public ThreadDemo() {
}
#Override
public void run() {
try {
while (true) {
int count = 0;
synchronized (lock) {
Thread.sleep(100);
while (count < 2) {
System.out.println(Thread.currentThread().getName() + " " + num++);
count++;
}
lock.notify();
lock.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class CoWorkingThreads {
public static void main(String[] args) {
Thread thread1 = new Thread(new ThreadDemo(), "First");
thread1.start();
Thread thread2 = new Thread(new ThreadDemo(), "Second");
thread2.start();
}
}
Finally use of a client provided lock object violates the encapsulation of synchronization policy. So I have used an internal private lock object instead.
Here's the new output.
First 1 First 2 Second 3 Second 4 First 5 First 6 Second 7
Second 8 First 9 First 10
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.
package atask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Q3Synchronization
{
Integer sum=new Integer(0);
Q3Synchronization(){
ExecutorService e=Executors.newFixedThreadPool(1000);
for(int i=0;i<1000;i++){
e.execute(new Sum());
}
e.shutdown();
while(!e.isTerminated()){
}
System.out.println(sum);
}
public static void main(String[]args){
new Q3Synchronization();
}
class Sum implements Runnable{
#Override
public void run() {
m();
}
public synchronized void m(){
sum=sum+1;
}
}
}
The question is:
(Synchronize threads) Write a program that launches 1,000 threads. Each thread adds 1 to a variable sum that initially is 0. You need to pass sum by reference to each thread. In order to pass it by reference, define an Integer wrapper object to hold sum. Run the program with and without synchronization to see its effect.
In short
Object method synchronization/locking works on a per-instance basis.
Explanation
You are creating 1000 instances of the Sum class. Every call to m() is synchronized but does not cause any other thread to wait. This is because there are no concurrent calls to the same instance, rather there are calls to different instances. I attached your code with a minor change:
Sum s = new Sum();
for(int i=0;i<1000;i++){
e.execute(s);
}
If you try this change, you will always get a result of 1000 in your counter variable.
In the constructor you are creating new Sum() instance and passing it to separate thread. The method m() is obtaining lock (every thread when entering in syncronized block must acquire lock) on object. Therefore each thread can execute m() method concurrently which breaks your multhreading logic since (sum = sum + 1) is not atomic operation.
You can fix it either:
change sum variable to Atomic Integer and use addAndGet() to perform addition . E.g.
AtomicInteger sum= new AtomicInteger(0);
and method m to use atomic integer
public void m(){sum.addAndGet(1);}
2.Use the same object to acquire lock, so that method m will be syncronized properly. You can achieve it by creating one sum instance variable in your constructor like this .
final Sum sum = new Sum();
for (int i = 0; i < 1000; i++) {
`e.execute(sum);
}
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
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.