Want a code for the difference between synchronized and asynchronized method - java

I am trying to set the difference between synchronized and unsynchronized methods.. I have tried following code
class Counter {
private int counter = 10;
public int getCounter() {
return counter;
}
public synchronized void doIncrementAndDecrement() {
counter++;
keepBusy(500);
counter--;
}
public void keepBusy(int howLong) { // (D)
long curr = System.currentTimeMillis();
while (System.currentTimeMillis() < curr + howLong)
;
}
}
class MyCounterThread extends Thread {
Counter c;
public MyCounterThread(Counter c, String name) {
// TODO Auto-generated constructor stub
super(name);
this.c = c;
start();
}
#Override
public void run() {
for (;;) {
c.doIncrementAndDecrement();
sleepForSometime();
System.out.println(c.getCounter());
}
}
public void sleepForSometime() { // (D)
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class UnSynchronizedExapmle {
public static void main(String[] args) throws InterruptedException {
Counter c = new Counter();
MyCounterThread t1 = new MyCounterThread(c, "A");
MyCounterThread t2 = new MyCounterThread(c, "B");
MyCounterThread t3 = new MyCounterThread(c, "C");
}
}
So above i have doIncrementAndDecrement() synchronized method..
So i expected the value of counter should be 10 every time. But this wont happen i have the output is like
10
10
11
10
10
10
10
11
10
10
11
10
11
11
10
10
11
10
11
10
10
10
11
10
10
11
10
So please help me why this happens.. Or any blog/article for explaining difference between synchronized and asynchronized methods

Your getCounter() method is not synchronized. So even though one thread might be locking the method, another thread can still access and print your counter variable

You codes do not synchronized the getCounter method so that System.out.println may output the innerstate of counter. synchronized on method is as same as synchronized(this).

... what difference it make if i write Thread.sleep() in my keepBusy() method.. because the output is quite different in both case.
What it does is to make keepBusy() take a long time, and hence it makes getCounter() wait for a long time.
The difference in the output is due to the synchronization which prevents getCounter() from ever "seeing" the counter in the incremented state.
I mean what do the difference make Thread.sleep() and the above while loop in keepBusy() method make in terms of thread scheduling or locking..
It makes no difference.
For the record, it would bad idea for a real program to have a method like keepBusy() that sleeps in a synchronized method or block. The sleep causes any other thread that is trying to synchronize on the target object to be blocked ... and that's liable to reduce your application's actual parallelism.

Related

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.

Why can't the main thread compare two variables that are updated by other threads?

I want to write two Threads that increment a number and decrement a number, and a main Thread that determines when the two numbers are equal. For example, one number starts at 0 and the other number starts at 10... When they are both 5, the main Thread should recognize they are equal and print "They meet!".
In this code, the main Thread can't not compare numup and numdown successfully:
public class Number implements Runnable {
public static int numup = 0;
public static int numdown = 10;
public Number() {
}
public static void main(String args[]) {
Number number = new Number();
Thread T1 = new Thread(number, "up");
Thread T2 = new Thread(number, "down");
T1.start();
T2.start();
while (true) {
if (numup == 5 && numdown == 5) {
System.out.println("Meet!");
System.exit(0);
}
}
}
public void run() {
while (true) {
if (Thread.currentThread().getName().equals("up")) {
numup++;
System.out.println(numup);
} else if (Thread.currentThread().getName().equals("down")) {
numdown--;
System.out.println(numdown);
}
try {
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("wake!");
}
}
}
}
The failed result:
1
9
8
2
7
3
6
4
5
5
6
4
7
3
8
2
1
9
However, when I make the main Thread sleep a few milliseconds, it works:
public class Number implements Runnable {
public static int numup = 0;
public static int numdown = 10;
public Number() {
}
public static void main(String args[]) {
Number number = new Number();
Thread T1 = new Thread(number, "up");
Thread T2 = new Thread(number, "down");
T1.start();
T2.start();
while (true) {
try {
Thread.sleep(10);
} catch (Exception e) {
System.out.println(Thread.currentThread().getName() + "was waked!");
}
if (numup == 5 && numdown == 5) {
System.out.println("They Meet!");
System.exit(0);
}
}
}
public void run() {
while (true) {
if (Thread.currentThread().getName().equals("up")) {
numup++;
System.out.println(numup);
} else if (Thread.currentThread().getName().equals("down")) {
numdown--;
System.out.println(numdown);
}
try {
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("wake!");
}
}
}
}
The successful result:
1
9
2
8
3
7
4
6
5
5
They Meet!
Why does the added delay make it work?
This could be because of the CPU cache. When the number thread updates the value of the variable (this goes from its CPU cache to main memory) by then the CPU cache of the corresponding main thread might not have got updated.
So when main thread check's the value of the variable it was still the old value.
You can use Volatile. OR
Use AtomicInteger for these operations.
You can refer to this link.
In a multithreaded application where the threads operate on non-volatile variables, each thread may copy variables from main memory into a CPU cache while working on them, for performance reasons. If your computer contains more than one CPU, each thread may run on a different CPU. That means, that each thread may copy the variables into the CPU cache of different CPUs.
With non-volatile variables there are no guarantees about when the Java Virtual Machine (JVM) reads data from main memory into CPU caches, or writes data from CPU caches to main memory.
Volatile:
public static volatile int numup = 0;
public static volatile int numdown = 10;
Atomic Integer:
import java.util.concurrent.atomic.AtomicInteger;
public class Number implements Runnable {
public static AtomicInteger numup = new AtomicInteger(0);
public static AtomicInteger numdown = new AtomicInteger(10);
public Number() {
}
public static void main(String args[]) {
Number number = new Number();
Thread T1 = new Thread(number, "up");
Thread T2 = new Thread(number, "down");
T1.start();
T2.start();
while (true) {
if (numup.get() == 5 && numdown.get() == 5) {
System.out.println("Meet!");
System.exit(0);
}
}
}
public void run() {
while (true) {
if (Thread.currentThread().getName().equals("up")) {
numup.incrementAndGet();
System.out.println(numup);
} else if (Thread.currentThread().getName().equals("down")) {
numdown.decrementAndGet();
System.out.println(numdown);
}
try {
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("wake!");
}
}
}
}
Quick answer - add volatile modifier to numdown and numup.
Long answer:
Your problem is that other thread can't see that numdown and numup has changed because of couple of reasons:
JVM may optimize and reorder the execution order of bytecode instructions.
Modern processors also do instruction reordering.
The value is cached in processor's cache line (L1, L2, L3 cache level).
So, when you introduce a volatile variable it is guaranteed by java that writes from one thread will have happen-before relationships with reads form another thus making changes visible to the another thread. On more low-level it could introduce a memory barrier
Anyway, it would not fit into the SO answer to explain properly how it's works, but there is a number of excellent resources you could read/watch if you're interested to dive deeper into the topic.
https://zeroturnaround.com/rebellabs/java-memory-model-pragmatics-by-aleksey-shipilev/
Do you ever use the volatile keyword in Java?
http://mechanical-sympathy.blogspot.com/2011/07/memory-barriersfences.html
Cheers!
Interesting one and a good answer given by Yegor. Just to add my observation that the program halts even if you write the if (numup == 5 && numdown == 5) check inside the while loop of the run() method.
In case you want to try out with the volatile keyword.
public static volatile int numup = 0;
public static volatile int numdown = 10;
volatile keyword will ensure that your threads won't cache the value of the variable and will always retrieve it from the main memory.

Java synchronization across methods [duplicate]

This question already has answers here:
Mutually exclusive methods
(5 answers)
Closed 6 years ago.
I am looking for a way to avoid the two methods from running concurrently, but not stopping one (or both) of them for running concurrently on their own. For example, in the code below, I must have method A run concurrently on the same object, but method B should block until there are no threads running Method A. Similarly, A should block if B is running on any thread and B can run concurrently with itself.
public void A() // calls from different threads on the same object allowed
{
....
} // A should only block if B is running
public void B() // calls from different threads on the same object allowed
{
....
} //B should only block if A is active
You could do something simple with an AtomicInteger, though it wouldn't be efficient.
static final AtomicInteger counter = new AtomicInteger();
public void methodA() {
for(;;) {
int v = counter.get();
if (v >= 0 && counter.compareAndSwap(v, v + 1))
break;
Thread.yield();
}
try {
// do something
} finally {
counter.decrementAndGet();
}
}
public void methodB() {
for(;;) {
int v = counter.get();
if (v <= 0 && counter.compareAndSwap(v, v - 1))
break;
Thread.yield();
}
try {
// do something
} finally {
counter.incrementAndGet();
}
}

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.

Java Volatile Variable

I am trying to understand volatile usage by the below example. I expect it to print 10 first and then 15 second. But most of the time i end getting 10 and 10.
Is some thing with the below code itself.
class T implements Runnable {
private volatile int x = 10;
#Override
public void run() {
if(x==10) {
System.out.println(x);
x = x+ 5;
} else if(x==15) {
System.out.println(x);
}
}
}
public class Prep {
public static void main(String [] args) {
T t1 = new T();
new Thread(t1).start();
new Thread(t1).start();
}
}
You just have a race condition: both threads run in parallel, and thus you have (for example)
thread 1 tests if x == 10 (true)
thread 2 tests if x == 10 (true)
thread 1 prints 10
thread 2 prints 10
...
The fact that x is volatile here is irrelevant. The only thing that volatile guarantees in this example is that if thread 1 has already incremented x when thread 2 reads its value, then thread 2 will see the incremented value. But it doesn't mean that the two threads can't run in parallel as shown above.
This will work :
public static void main(String[] args) {
T t1 = new T();
new Thread(t1).start();
try {
Thread.currentThread().sleep(1000); // sleeping for sometime .
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Thread(t1).start();
}
answer : 10 15
Reason : The operations
if(x==10) {
System.out.println(x);
might have executed first for the first thread, then context would have switched back to Thread2 (race condition as JB Nizet explains..) so when both threads print the value of x, it is still 10.

Categories

Resources