Java synchronized function work while synchronized block not work [duplicate] - java

This question already has answers here:
Synchronizing on an Integer value [duplicate]
(9 answers)
Closed 7 years ago.
takeAmount and addAmount is simply to add/sub value from balanceAccount(eg. add 11,12...,20 or add 101,102...,110). balanceAccount have two version one is using synchronized function and other is using synchronized block.
Is that any different between BalanceAccount_synchronizedBlock and BalanceAccount_synchronizedFunction?
Indeed BalanceAccount_synchronizedFunction always return 0, while BalanceAccount_synchronizedBlock doesn't.
And...why it will show different behavior?
public class mainStart {
public static void main(String args[])
{
for (int i=1;i<3000;i=i+10)
{
new Thread(new addAmount(i)).start();
new Thread(new takeAmount(i)).start();
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//BalanceAccount_synchronizedBlock.printAmount();
BalanceAccount_synchronizedFunction.printAmount();
}
}
class takeAmount implements Runnable {
private int startFrom;
public takeAmount(int start)
{
this.startFrom=start;
}
public void run()
{
for (int i=startFrom;i<startFrom+10;i++)
//BalanceAccount_synchronizedBlock.sub(i);
BalanceAccount_synchronizedFunction.sub(i);
}
}
class addAmount implements Runnable {
private int startFrom;
public addAmount(int start)
{
this.startFrom=start;
}
public void run()
{
for (int i=startFrom;i<startFrom+10;i++)
//BalanceAccount_synchronizedBlock.add(i);
BalanceAccount_synchronizedFunction.add(i);
}
}
public class BalanceAccount_synchronizedBlock {
public static Integer amount=0;
public static void add(int a)
{
synchronized (amount)
{
amount = amount + a;
}
}
public static void sub(int a)
{
synchronized (amount)
{
amount = amount - a;
}
}
public synchronized static void printAmount()
{
System.out.println("Amount " + amount);
}
}
public class BalanceAccount_synchronizedFunction {
public static Integer amount=0;
public synchronized static void add(int a)
{
amount = amount + a;
}
public synchronized static void sub(int a)
{
amount = amount - a;
}
public synchronized static void printAmount()
{
System.out.println("Amount " + amount);
}
}

Synchronizing a method uses the enclosing class as a synchronization token. When you write synchronized(amount) you are using an Integer instance as a synchronization token. As you are not using the same token in both cases, the lock will not occur as expected.
Also note that Integer is immutable, and every time you reassign a value into amount, you are creating a new instance an lose whatever lock you may have had on the previous value.

Your print method is defined as
public synchronized static void printAmount()
which is synchronized on the class itself. In the case of your "block" attempt, the blocks are synchronizing on amount, while the print method is synchronizing on the class. Change that method to use a block also synchronized on amount.
As Kayaman pointed out, you also have the problem that you're synchronizing on a variable (amount) whose referent is constantly changing. Instead, declare a private static final Object LOCK = new Object() that is used only for synchronization--or better yet, just use AtomicInteger.

You can either lock using object which is calling this method by using
synchronized (this) { // this is similar to method level synchronization
Or using another class level Object other then amount integer(as #Kayaman pointed out, it is immutable so every time new integer object is created when you update it)
public class BalanceAccount_synchronizedBlock {
public static Integer amount=0;
public static Object Lock = new Object();
public static void add(int a) {
synchronized (Lock) {
amount = amount + a;
}
}

Related

Setting and accessing a varibale by two different threads

I have two threads, one setting a variable of a class, and the other one accessing the variable by a get method.
public class Parent {
private int value = -1
public int getValue()
return this.value;
}
public void setValue(int value){
this.value = value;
}
private class UpdatingVaribale extends Thread {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
setValue(2);
Thread.currentThread().interrupt();
}
}
}
}
private class GettingVaribale extends Thread {
public void run() {
while (getValue == -1) {
try{
System.out.println(getValue);
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
System.out.println(getValue);
}
}
The problem is that the condition of the while loop in the second thread is always true. The System.out.println(getValue) always prints -1. I am wondering why the second thread doesn't get the new value of value which is 2. I don't think the synchronized matters here since one thread is setting a variable and the other one just accessing the variable.
There are some solutions here:
use standard Java class AtomicInteger for storing your value in multi-threaded safe way. Actually it's the best and fastest way.
add synchronized keyword to your getValue and setValue methods
add volatile java keyword to i field definition
The source of your problem is i variable value actually looks different in different threads cause of CPU speed and memory optimization and you have to specify JVM somehow don't to do this optimization and - opposite - makes the latest i value visible in all threads.
UPDATE code for testing
public class SyncProblem {
public static void main(String[] args) {
Parent parent = new Parent();
new Thread(parent.new GettingVaribale()).start();
new Thread(parent.new UpdatingVaribale()).start();
}
}
class Parent {
private volatile int value = -1;
public int getValue() {
return this.value;
}
public void setValue(int value) {
this.value = value;
}
class UpdatingVaribale implements Runnable {
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
setValue(2);
Thread.currentThread().interrupt();
}
}
}
class GettingVaribale implements Runnable {
#Override
public void run() {
while (getValue() == -1) {
try {
System.out.println(getValue());
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
System.out.println(getValue());
}
}
}

All threads get locked in wait() state [duplicate]

This question already has answers here:
Notify not getting the thread out of wait state
(3 answers)
Closed 7 years ago.
Basically I have to create 3 classes (2 threaded).
First one holds some cargo (has a minimum capacity (0) and a maximum (200))
Second one supplies the cargo every 500ms.
Third one takes away from cargo every 500ms.
Main program has one cargo class(1), 2 supplier classes(2) and 2 substraction classes(3). Problem I'm having is that one by one, they're falling into a wait(); state and never get out. Eventually all of them get stucked in the wait() state, with the program running, but without them actually doing anything.
First class:
public class Storage {
private int maxCapacity;
private int currentCapacity;
public Storage( int currentCapacity, int maxCapacity ) {
this.currentCapacity = currentCapacity;
this.maxCapacity = maxCapacity;
}
public int getCapacity(){ return this.currentCapacity; }
public void increase( int q ) {
this.currentCapacity += q;
System.out.println("increase" + q + ". Total: " + currentCapacity);
}
public int getMax() { return this.maxCapacity; }
public void decrease( int q ) {
this.currentCapacity -= q;
System.out.println("decrease - " + q + ". Total: " + currentCapacity);
}
}
2nd class (supplier):
public class Supplier implements Runnable {
private int capacity;
private Storage storage;
private volatile boolean run;
public Supplier( int capacity, Storage storage ) {
this.capacity = capacity;
this.storage = storage;
this.run = true;
}
public void kiss_kill() { run = !run; }
public synchronized void add() {
while(storage.getCapacity() + capacity > storage.getMax()) {
try {
System.out.println("wait - supplier");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
storage.increase(capacity);
notifyAll();
}
public void run() {
synchronized (this) {
while(run) {
add();
Thread.yield(); //would be wait(500), but this just speeds it up
}
}
}
}
3rd class (taker/demander):
public class Taker implements Runnable {
private int capacity;
private Storage storage;
private volatile boolean run;
public Taker( int capacity, Storage storage ) {
this.capacity = capacity;
this.storage = storage;
this.run = true;
}
public void kiss_kill() { run = !run; }
public synchronized void take() {
while(storage.getCapacity() - capacity < 0) {
try {
System.out.println("wait - taker");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
storage.decrease(capacity);
notifyAll();
}
public void run() {
synchronized (this) {
while(run) {
take();
Thread.yield(); //again, wait(500) should be instead
}
}
}
}
Main is something like this:
public class Main{
public static void main(String... args) {
Storage sk = new Storage(100, 200);
Supplier[] s = { new Supplier(10, sk), new Supplier(15, sk) };
Taker[] p = { new Taker(15, sk), new Taker(20, sk) };
Thread t[] = {
new Thread(s[0]),
new Thread(s[1]),
new Thread(p[0]),
new Thread(p[1]) };
for(Thread th : t) th.start();
try {
Thread.sleep(60000); //program should last for 60s.
} catch (InterruptedException e) {
e.printStackTrace();
}
s[0].kiss_kill(); s[1].kiss_kill(); p[0].kiss_kill(); p[1].kiss_kill();
}
}
Why doesn't notifyAll() release the wait() state of other object? What could I do to fix this?
Sorry, I know it's a long example, I hate posting too many classes like this. Thanks for reading!
I translated the code, so if you spot anything that you're unsure about that I've missed, please tell me and I'll fix it right away!
Doing concurrency is easy:
Anyone can slap synchronized on methods and synchronized () {} around blocks of code. It does not mean it is correct. And then they can continue to slap synchronized on everything until it works until it doesn't.
Doing concurrency correctly is Hard:
You should lock on the data that needs to be consistent not the methods making the changes. And you have to use the same lock instance for everything.
In this case that is the currentCapacity in Storage. That is the only thing that is shared and the only thing that needs to be consistent.
What you are doing now is having the classes lock on instances of themselves which means nothing shared is being protected because there is no shared lock.
Think about it, if you are not locking on the same exact instance which must be final of an object then what are you protecting?
Also what about code that has access to the object that needs to be consistent and does not request a lock on it. Well it just does what it wants. synchronized() {} in calling classes is not how you protect shared data from external manipulation.
Thread safe objects are NOT about the synchronized keyword:
Read up on the java.util.concurrent package it has all the things you need already. Use the correct data structure for your use case.
In this particular case if you use AtomicInteger for your counter, you do not need any error prone manual locking, no need for synchronized anywhere, it is already thread safe.
Immutable Data:
If you work with immutable data exclusively you do not need any of this silly locking semantics that are extremely error prone for even those that understand it and even more so for those that think they understand it.
Here is a working idiomatic example:
This is a good chance to learn what non-deterministic means and how to use the step debugger in your IDE to debug concurrent programs.
Q33700412.java
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import com.vertigrated.FormattedRuntimeException;
public class Q33700412
{
public static void main(final String[] args)
{
final Storage s = new Storage(100);
final int ap = Runtime.getRuntime().availableProcessors();
final ExecutorService es = Executors.newFixedThreadPool(ap);
for (int i = 0; i < ap; i++)
{
es.execute(new Runnable()
{
final Random r = new Random();
#Override
public void run()
{
while (true)
{
/* this if/else block is NOT thread safe, I did this on purpose
the state can change between s.remainingCapacity() and
the call to s.increase/s.decrease.
This is ok, because the Storage object is internally consistent.
This thread might fail if this happens, this is the educational part.
*/
if (s.remainingCapacity() > 0)
{
if (r.nextBoolean()) { s.increase(r.nextInt(10)); }
else { s.decrease(10); }
System.out.format("Current Capacity is %d", s.getCurrentCapacity());
System.out.println();
}
else
{
System.out.format("Max Capacity %d Reached", s.getMaxCapacity());
System.out.println();
}
try { Thread.sleep(r.nextInt(5000)); }
catch (InterruptedException e) { throw new RuntimeException(e); }
}
}
});
}
es.shutdown();
try
{
Thread.sleep(TimeUnit.MINUTES.toMillis(1));
es.shutdown();
}
catch (InterruptedException e) { System.out.println("Done!"); }
}
public static final class Storage
{
/* AtomicInteger is used so that it can be mutable and final at the same time */
private final AtomicInteger currentCapacity;
private final int maxCapacity;
public Storage(final int maxCapacity) { this(0, maxCapacity); }
public Storage(final int currentCapacity, final int maxCapacity)
{
this.currentCapacity = new AtomicInteger(currentCapacity);
this.maxCapacity = maxCapacity;
}
public int remainingCapacity() { return this.maxCapacity - this.currentCapacity.get(); }
public int getCurrentCapacity() { return this.currentCapacity.get(); }
public void increase(final int q)
{
synchronized (this.currentCapacity)
{
if (this.currentCapacity.get() < this.maxCapacity)
{
this.currentCapacity.addAndGet(q);
}
else
{
throw new FormattedRuntimeException("Max Capacity %d Exceeded!", this.maxCapacity);
}
}
}
public int getMaxCapacity() { return this.maxCapacity; }
public void decrease(final int q)
{
synchronized (this.currentCapacity)
{
if (this.currentCapacity.get() - q >= 0)
{
this.currentCapacity.addAndGet(q * -1);
}
else
{
this.currentCapacity.set(0);
}
}
}
}
}
Notes:
Limit the scope of synchronized blocks to the minimum they need to protect and lock on the object that needs to stay consistent.
The lock object must be marked final or the reference can change and you will be locking on different instances.
The more final the more correct your programs are likely to be the first time.
Jarrod Roberson gave you the "how" half of the answer. Here's the other half--the "why".
Your Supplier object's add() method waits on itself (i.e., on the supplier object), and it notifies itself.
Your Taker object's take() method waits on its self (i.e., on the taker object), and it notifies its self.
The supplier never notifies the taker, and taker never notifies the supplier.
You should do all of your synchronization on the shared object (i.e., on the Storage object.
So I should convert storage into a thread?
No, you don't want Storage to be a thread, you want it to be the lock. Instead of having your Supplier objects and your Taker objects synchronize on themselves, they should all synchronize on the shared Storage object.
E.g., do this:
public void take() {
synchronized(storage) {
while(...) {
try {
storage.wait();
} catch ...
}
...
storage.notifyAll();
}
}
Instead of this:
public synchronized void take() {
while(...) {
try {
wait();
} catch ...
}
...
notifyAll();
}
And do the same for all of your other synchronized methods.

why is this synchronized method not working as expected? [duplicate]

This question already has an answer here:
why Synchronized method allowing multiple thread to run concurrently?
(1 answer)
Closed 7 years ago.
I have a class called MyRunnable:
public class MyRunnable extends Main implements Runnable {
String name; // name of thread
Thread t;
MyRunnable (String threadname) {
name = threadname;
t = new Thread(this, name);
t.start();
}
public void run() {
try {
for (int i=0;i<100000;i++) {
extend(1);
}
} catch (InterruptedException e) {
System.out.println("Thread interrupted.");
}
System.out.println("Thread " + name + " exiting.");
}
}
and a class called Main:
public class Main {
private static List<Integer> numbers=new ArrayList<>();
public synchronized void extend (int i) throws InterruptedException {
numbers.add(i);
}
public synchronized static int getSize() {
return numbers.size();
}
public static void main(String[] args) {
MyRunnable t0=new MyRunnable("0");
MyRunnable t1=new MyRunnable("1");
MyRunnable t2=new MyRunnable("2");
try {
t0.t.join();
t1.t.join();
t2.t.join();
} catch (InterruptedException e) {
}
System.out.println(getSize());
}
}
Now I would be expecting to get 300000 as output but instead I get a random number (approx. between 250000 and 290000) even though I did use synchronized methods. I did read the oracle's documentation http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html but I can't seem to figure out why this is not working as expected. Could someone explain me why ?
Thanks in advance
Methods are synchronized to the object calling them. You need to create an object shared between each of the objects and have them synchronize on that object.
private static List<Integer> numbers=new ArrayList<>();
public synchronized void extend (int i) throws InterruptedException {
synchronize(numbers) {
numbers.add(i);
}
}
synchronized here locks on the object against which the method extend is invoked (since it is an instance method). Therefore, you're synchronizing on three different objects.
If you synchronize on the shared static list (for example), you would get the expected result.

synchronization not working after making object synchronized

I have synchronized Integer object a and I am expecting output 1 2 3 4 5 6 7 8 9
but still it is giving me other output.Where is the problem as I have synchronized the variable where each thread was trying to access.
package thread;
public class BasicThread extends Thread {
static Integer a=new Integer(0);
void incr() {
synchronized (a) {
a++;
System.out.println(a);
}
}
public void run() {
incr();
incr();
incr();
}
public static void main(String[] args) throws InterruptedException {
BasicThread bt=new BasicThread();
BasicThread bt1=new BasicThread();
BasicThread bt2=new BasicThread();
bt.start();
bt1.start();
bt2.start();
}
}
Please note: Integer objects are immutable. So, what happens here is: every time you do a "a++" ... the compiler actually does auto-boxing; and in the end ... a new Integer object is created.
In order for your code to work, your lock (the object you are synchronizing on) must be the same for all calls to the method.
In other words: a reference to an object that is constantly changed ... is not a good candidate to be used as lock. Instead, do something like:
private final static Object LOCK = new Object();
(where usage of final helps to ensure that this object reference will not change over time) and then:
synchronized(LOCK)
Use a unique Object to synchronize on. When you change your Integer a new one is created since they're immutable.
Example:
public class BasicThread extends Thread {
static Integer a = new Integer(0);
private static String ab = "";
void incr() {
synchronized (ab) {
a++;
System.out.println(a);
}
}
public void run() {
incr();
incr();
incr();
}
}

Synchronization Block

I am new to threads in Java and hence have this doubt. I read that a 'synchronized non-static method block' allows only one thread to enter the block (for one instance of non-static block, of-course). However it doesn't seem to work. Am I missing something?
Look at the following code.
class A extends Thread
{
public void run()
{
B.b.add();
}
}
class B
{
static B b=new B();
int i;
public synchronized void add()
{
i++;
}
}
public class Sample
{
public static void main(String[] args)
{
for(int i=0;i<10;i++)
{
new A().start();
}
System.out.println(B.b.i);
}
}
One problem here is that your main thread doesn't wait for the other threads to finish before it tries to retrieve the result. Using Thread#join works if you want to wait for a single thread, but here we want to wait for all 10. Modifying the program to use CountDownLatch makes the main thread wait until all the threads it created are finished.
Another problem is that the updated value of i isn't guaranteed to be visible. JVM implementations differ about how aggressively they perform optimizations (like delaying refreshes of cached values, or reordering bytecode) that may make the changes to i not visible to the main thread. Adding a synchronized method on the same lock as the add method to fetch the value of i fixes the visibility issue.
import java.util.concurrent.CountDownLatch;
class A extends Thread {
private CountDownLatch latch;
public A(CountDownLatch latch) {
this.latch = latch;
}
#Override public void run() {
B.b.add();
latch.countDown();
}
}
class B {
static B b=new B();
int i;
public synchronized void add() {
i++;
}
public synchronized int getI() {
return i;
}
}
public class Sample {
public static void main(String[] args) throws Exception {
CountDownLatch latch = new CountDownLatch(10);
for(int i=0;i<10;i++) {
new A(latch).start();
}
latch.await();
System.out.println(B.b.getI());
}
}

Categories