Why isn't synchronization taking place in this code? - java

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);
}

Related

Java multi threaded counter is not working

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.

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.

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

synchronized block for an Integer object

I just came across the synchronized block in Java and wrote a small programm to test how it works.
I create 10 threads and let each thread increment an Integer object 1000 times.
So with synchronization I would assume a result of 10000 after all threads have finished their work and a result of less than 10000 without synchronization .
However the synchronization is not wokring as I expected.
I guess it has something to do with immutability of the object or so.
My program:
public class SyncTest extends Thread{
private static Integer syncObj = new Integer(0);
private static SyncTest[] threads = new SyncTest[10];
private boolean done = false;
public void run(){
for(int i = 0; i < 1000; i++){
synchronized(syncObj){
syncObj ++;
}
}
done = true;
}
public static void main(String[] args) {
for(int i=0; i < threads.length; i++){
threads[i] = new SyncTest();
threads[i].start();
}
while(!allDone()); //wait until all threads finished
System.out.println(syncObj);
}
private static boolean allDone(){
boolean done = true;
for(int i = 0; i < threads.length; i++){
done &= threads[i].done;
}
return done;
}
}
Can someone clarify this?
syncObject is changing each time you ++ it (the ++ is converting it to a primitive int, incrementing it, and then autoboxing it back to the Integer object. Integer objects are immutable ... once they are created, they cannot change.
Bottom ine is that you are not using the same syncPObj in all the threads, different threads use different syncObjects at different times to sync on.
use one object as the synchronization (call it syncObj), and declare it as a final Object:
private static final Object syncObject = new Object();
Then your counter should be a primitive (int) for perofrmance, call it 'counter' or something.
Synchronize on syncObject, and increment counter.
Edit: as per #jsn, the done flag is also broken in that your code has a 'tight loop' on the isAllDone() method, and that is bad practice. You should use thread[i].join() to wait (blocking) on each thread's completion, and then check the status from that. Using an ExecutorService is the 'right way'.
As assumed it is because of the immutability of the Integer object.
I've changed the synchonized block to
Integer old = syncObj;
syncObj ++;
System.out.println(syncObj == old);
and my console gets filled with falses
So each time I increment the Integer a new object is createt.
Therefore I only read from the old Object and it will not be locked.
These operations are usually done with Atomic. Have a look here. These structures are specifically designed for multi-threaded computation. Normal implementations are not thread safe.

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

Categories

Resources