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();
}
}
Related
My code basically goes like this:
//in Main Thread: (myList is a volatile field)
myList = new ArrayList<myClass>();
Thread myThread = new Thread(new MyCustomRunnable(myList));
myThread.start();
//some lines of code NOT involving myList
myThread.join();
//myList appears empty here even though I can see that the list has been populated
//in the other thread
Is there a reason for this behavior? Like I said, i can see in the debugger that the list has been populated in the called thread, but these changes don't appear in the caller thread after the join() method. MyCustomRunnable also declares the ArrayList as a volatile field, assigned by the constructor.
UPDATE:
Ok, I made a simpler program, replacing the ArrayList with a simple Integer and the results are the same...
public class Threading {
private volatile static Integer i = 0;
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new MyCustomRunnable(i));
t.start();
t.join();
System.out.println(i); //prints '0', I expected '1'
}
}
public class MyCustomRunnable implements Runnable {
private volatile Integer i;
public MyCustomRunnable(Integer i) {
this.i = i;
}
public void run() {
this.i = 1;
}
}
Why isn't the Integer's value updated in the main Thread?
Add
public static void setI(int i) {
Threading.i = i;
}
to your Threading class and in your runnable add
public void run() {
this.i = 1;
Threading.setI(1);
}
This has nothing to do with multithreading, just variable scoping. i in the Threading class is not updated in MyCustomRunnable's run method.
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;
}
}
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());
}
}
To prove initialization safety for immutable objects, I wrote a small program. Even though fields were final, second thread was able to view the half-constructed object being created by the first thread. Have I got the concept wrong or "object escaping" can cause it? Second thread first printed "10 null" and then after half of the iterations it started printing "10 apple".
package test;
import java.util.ArrayList;
import java.util.List;
public final class ObjectEscape implements Runnable {
private final int a;
private final String b;
//this list is defined somewhere else
public static volatile List<ObjectEscape> globalList = new ArrayList<ObjectEscape>();
public ObjectEscape () throws InterruptedException {
a = 10;
globalList.add(this);
Thread.sleep(10);
b = "apple";
System.out.println("done");
}
public ObjectEscape(int a) {
this.a = 1;
b = "";
}
public static void main(String are[]) throws InterruptedException{
Thread t = new Thread(new ObjectEscape(1));
t.start();
ObjectEscape oe1 = new ObjectEscape();
}
#Override
public void run() {
int i=0;
while(i<10) {
if(globalList.get(0) != null)
System.out.println(globalList.get(0).a+" "+globalList.get(0).b);
i++;
}
}
}
final fields are guaranteed to have been initialized when the contructor call finishes. Naturally, a "leaking this" will subvert the value of this guarantee:
globalList.add(this); // ObjectEscape.<init> has not finished yet
See also: Java leaking this in constructor
I am new to threads and learning. Why does this data race? I know how to do it using the Synchronized(){} method but not with the modifier.
public class SyncMethodDataRace extends Thread {
private static int common = 0;
public synchronized void run(){
int local = common;
local++;
common = local;
}
public static void main(String[] args) throws InterruptedException {
SyncMethodDataRace[] allThreads = new SyncMethodDataRace[20000];
for(int i = 0; i < allThreads.length; i++){
allThreads[i] = new SyncMethodDataRace();
}
for(SyncMethodDataRace d: allThreads){
d.start();
}
for(SyncMethodDataRace d: allThreads){
d.join();
}
System.out.println(common);
}
}
By making run method synchronized you did not achieve the desired synchronization. A synchronized method locks on the current instance of the class. In your example, no other thread is calling the run method of another thread, so there is no blocking.
In your case you probably need a static object that is shared among all instances to synchronize on, ie:
private static Object syncObject = new Object();
public void run() {
synchronized (syncObject) {
//....
}
}