• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Bear Bibeault
  • Junilu Lacar
Sheriffs:
  • Jeanne Boyarsky
  • Tim Cooke
  • Henry Wong
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • salvin francis
  • Frits Walraven
Bartenders:
  • Scott Selikoff
  • Piet Souris
  • Carey Brown

How a method on stack knows that to which object on heap it is connected?

 
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
if there are two threads, A and B, and if thread A calls a method-method1 on an object and while the method1 is running the Thread B sets the reference ( the same reference which thread A used to call the method1) to a new object.
Then shall the method1 now have access to the instance variables of new object or the old object with which it was invoked.

class Test1
{
int i;
Test1(int j)
{
i=j;
}
public void method1()
{
if(!i==i)
{
sysout("something wrong");
}
}
}

Class Test2{
Test1 test1= new Test(0);

public void init()
{ test1=new Test(20);}

public void callToMethod1()
{
test1.method1();
}

}
 
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think I just answered this in another thread, either in a different category here or on OTN.

Caveat respondor.
 
Marshal
Posts: 70308
283
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You don’t seem to have answered it here. There is a pointer to the object on the stack as well.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:You don’t seem to have answered it here.


Right. Why repeat myself? Same poster, same question
https://coderanch.com/t/559007/threads/java/method-stack-knows-which-object


There is a pointer to the object on the stack as well.



Yeah, that's sort of a side effect of what I explained in the crosspost, and a bit lower level I think than where the OP's confusion lies.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Guriqbal, in the future, please CarefullyChooseOneForum and post your question only once.
 
Campbell Ritchie
Marshal
Posts: 70308
283
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry, I was mistaken. The other discussion has been closed.
 
guriqbal sandhu
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I was reading java concurrency in practice and I saw a similar example according to which the method1 should print"something wrong".
The example goes like:

// Unsafe publication
public Holder holder;
public void initialize() {
holder = new Holder(42);
}


public class Holder {
private int n;
public Holder(int n) { this.n = n; }
public void assertSanity() {
if (n != n)
throw new AssertionError("This statement is false.");
}
}

the explanation says that if the assertSanity function is called by some other thread than the publishing thread then the former may throw assertion error.
But like you said that the assertSanity would have had its reference to the object and the initialization by the publishing thread should not affect it, then how can it thow asseertion error.


Thanks
 
guriqbal sandhu
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Jeff Verdegan wrote:Guriqbal, in the future, please CarefullyChooseOneForum and post your question only once.


I will take care of this.
Thanks
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

guriqbal sandhu wrote:I was reading java concurrency in practice and I saw a similar example according to which the method1 should print"something wrong".
The example goes like:

// Unsafe publication
public Holder holder;
public void initialize() {
holder = new Holder(42);
}


public class Holder {
private int n;
public Holder(int n) { this.n = n; }
public void assertSanity() {
if (n != n)
throw new AssertionError("This statement is false.");
}
}

the explanation says that if the assertSanity function is called by some other thread than the publishing thread then the former may throw assertion error.
But like you said that the assertSanity would have had its reference to the object and the initialization by the publishing thread should not affect it, then how can it thow asseertion error.


Thanks



I also said if a given thread has to evaluate the same variable twice, then it may see different values on the two evaluations. For "if (n != n)", we have to read the n variable twice. Between those two reads, another thread can come in and change n's value.


Here's what I said in your other thread...

- - - - - - - - - - - - -

Thread A looks at some shared variable, and gets its value. That value is a reference. TA uses that reference to invoke some method. While that method is running, TB changes the value of the shared reference variable, so now that variable points to a different object. But TA doesn't know or care, because it has already evaluated that variable's value and found the object it pointed to at that time. It was done with the shared variable before it ever called the method.

Of course, if TA does
view plaincopy to clipboardprint?

obj.var.x();
obj.var.y();


and somewhere in the middle of that, TB comes along and changes the value of obj.var so it points to a different object, then, TA's x() call will be on one object and its y() call will be on a different one, because it had to evaluate obj.var twice.

- - - - - - - - - - - - -

The "n != n" code you're asking about here is like the "obj.var.x(); obj.var.y();" calls above.
 
guriqbal sandhu
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

obj.var.x();
obj.var.y();


here var means that it is a reference type but in our code it is a primitive.

The method assertsanity() is called on the obj and the stack keeps this reference to the actual object on heap which has the 'int i' in it.
The other thread comes and makes the obj now point to a new object on heap.
How the second look for int i may fetch the int i from new object, if the stack had reference to old object. How the reference changed.

if 'i' had been a reference type then it was understandable to me.

but in our case the value of 'i' in the old object hasnot changed.

Thanks
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

guriqbal sandhu wrote:

obj.var.x();
obj.var.y();


here var means that it is a reference type but in our code it is a primitive.



That's irrelevant.
Notice how similar the following two statements look.


The method assertsanity() is called on the obj and the stack keeps this reference to the actual object on heap which has the 'int i' in it.



No. Whether the variable obj is on the stack or on the heap does not matter. It is one place or the other, and it never changes where it lives. The variable that changes is obj.var. I specifically made it that way to make it clear that it must be a variable on the heap. Only variables on the heap (member variables) can be shared. Variables on the stack (local variables) cannot be shared.

So TA and TB both point to some object. TA points to it through its obj variable. Both threads see the same shared variable inside that object, the variable that is named var.

TA calls obj.var.x();
TB executes obj.var = somethingElse; (maybe even while TA is executing x())
TA calls obj.var.y();

At the x() call, var is pointing to one object. At the y() call, it's pointing to a different object.

However, during the x() call or y() call, it doesn't matter what any thread does to that variable. TA doesn't keep evaluating it during that x() call (unless, in the body of x(), there is a reference to that own object's var, but in that case, that's the same as the y() call in the example).

The other thread comes and makes the obj now point to a new object on heap.



No, it changes var, not obj.

How the second look for int i may fetch the int i from new object, if the stack had reference to old object. How the reference changed.

if 'i' had been a reference type then it was understandable to me.



You mean "n"? It doesn't matter if it's a primitive or not. It's a member variable, so is can be shared among multiple threads. If TA and TB are both refering to the same Holder object that contains n, then if TB changes that Holder object's "n" variable between the two evaluations of "n" in "n != n", then that expression will evaluate to false.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

guriqbal sandhu wrote:
if 'i' had been a reference type then it was understandable to me.



I don't know why you would think that would make a difference. Threads share variables, not objects. And if one thread changes the value of a shared variable, another thread can see that new value. It doesn't matter if the variable's value is a primitive or a reference.
 
guriqbal sandhu
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

So TA and TB both point to some object. TA points to it through its obj variable. Both threads see the same shared variable inside that object, the variable that is named var.


I made a mistake in understanding your analogy earlier.

TA calls obj.var.x();
TB executes obj.var = somethingElse; (maybe even while TA is executing x())


ok. I am only thinking of TB updating var while TA is executing x() here.

At the x() call, var is pointing to one object. At the y() call, it's pointing to a different object.


agree

However, during the x() call or y() call, it doesn't matter what any thread does to that variable. TA doesn't keep evaluating it during that x() call



During the x() call or during the assertSanity() call thread A wont keep on recalculating the holder reference and so during the assertcall() it should return same value of i and hence there should not be any assertion error.

Thanks
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

guriqbal sandhu wrote:

However, during the x() call or y() call, it doesn't matter what any thread does to that variable. TA doesn't keep evaluating it during that x() call



During the x() call or during the assertSanity() call thread A wont keep on recalculating the holder reference



Correct. There is no such thing as "calculating a reference". At least not in this context. The closest thing to "calculating a reference" would be "evaluating a reference-type expression". That is looking into obj.var or into n to see what value it holds. It only does that where you tell it to do that in your code. (And, as I mentioned earlier, if inside the body of x(), there is code to read var, like var2 = var;, then, yes, at that point it will once again evaluate the expression "var" to see what reference value it produces.) But it is NOT the case that it just sits there and spins and re-reads var over and over again constantly.

and so during the assertcall() it should return same value of i and hence there should not be any assertion error.



Sorry, I've lost track of which code is which, so I'm not sure what you're saying here.
 
guriqbal sandhu
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Jeff, I appreciate your help.
My concern for starting this thread was that whether the following code should throw an error or not?

// Unsafe publication
public Holder holder;
public void initialize() {
holder = new Holder(42);
}


public class Holder {
private int n;
public Holder(int n) { this.n = n; }
public void assertSanity() {
if (n != n)
throw new AssertionError("This statement is false.");
}
}
 
guriqbal sandhu
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

However, during the x() call or y() call, it doesn't matter what any thread does to that variable.


I think this applies to the above example.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

guriqbal sandhu wrote:Thanks Jeff, I appreciate your help.
My concern for starting this thread was that whether the following code should throw an error or not?



It can throw the exception. As I've been saying: The "if (n != n)" part requires two reads of the "n" variable. If another thread modifies n between the first read and the second read, then the two reads will have different values, "n != n" will be true, and the exception will be thrown.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

guriqbal sandhu wrote:

However, during the x() call or y() call, it doesn't matter what any thread does to that variable.


I think this applies to the above example.



No. It does not.

For the x() or y() call, we are reading the shared variable "var" once, before the method call.

This case is different because we are reading the shared variable "n" twice.

Perhaps you're getting confused because in the x()/y() example, the read of the variable is done in order to make a method call, whereas in the "n" case, it is not. Ignore the x() and y() method calls in that example, and just consider the read of the "var" variable. That is the equivalent to the read of the "n" variable here. In both cases the first read of the variable can produce a different value than the second read. The fact that we use the result of reading "var" to call x() or y() does not matter.
 
Don't get me started about those stupid light bulbs.
    Bookmark Topic Watch Topic
  • New Topic