GeeCON Prague 2014*
The moose likes Threads and Synchronization and the fly likes any thread that has a reference to another thread can execute any method of that othe Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "any thread that has a reference to another thread can execute any method of that othe" Watch "any thread that has a reference to another thread can execute any method of that othe" New topic
Author

any thread that has a reference to another thread can execute any method of that othe

Nicholas Jordan
Ranch Hand

Joined: Sep 17, 2006
Posts: 1282
p. 35, Java Threads:

".. any thread that has a reference to another thread can execute any method of that other thread's object."


Admittiedly written to address the question, t-1 is now already running - a list of machine ops, conceptually - and if t_2/t_3 actually doSomething(), then the JVM has called re-entrant code in a sense that cannot be visualized by the cursor moving through the source code.


P.S. should I make a separate thread to ask if non-blocking read() of System.in is discussed in Java Threads ? Scanner docs on Sun Java docs state: "will block if no data is available." I have other approaches in mind, but this block()'ing is difficult to code around if I cannot read the sources for the JVM, which is a constraint I must work under.
[ January 02, 2007: Message edited by: Nicholas Jordan ]

"The differential equations that describe dynamic interactions of power generators are similar to that of the gravitational interplay among celestial bodies, which is chaotic in nature."
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
the JVM has called re-entrant code in a sense that cannot be visualized by the cursor moving through the source code


If I grasp what you mean by this, it's true any time you have multiple threads. You can imagine the instructions to be executed on each thread as a set of columns down a page. The JVM will execute a few from one column, then a few from another column, then a few from another. The "cursor" or the virtual "next instruction" pointer bounces around between threads. The thread manager has a cursor or pointer per thread. It saves the pointer when leaving one column and restores it when coming back to the column.

any thread that has a reference to another thread can execute any method of that other thread's object.


Yes, they have to be able to communicate somehow. Consider this common design:

You might start this thread and let it run on its own until the user hits "cancel" or "file/exit". Then you'd have a stored reference to the thread and call quit().

PS - Yes, start another thread for the other question. I didn't get that one yet.


A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

Your thread does not use the thread that is passed to it. So while it can call methods on that other thread, you are not doing so.
Nicholas Jordan
Ranch Hand

Joined: Sep 17, 2006
Posts: 1282
Originally posted by Stan James:
Yes, they have to be able to communicate somehow. Consider this common design:

You might start this thread and let it run on its own until the user hits "cancel" or "file/exit". Then you'd have a stored reference to the thread and call quit().

These things can be dicey to visualize, the "each thread as a set of columns down a page" metaphor I have already written for my team lead to suggest that we should use Java as the shell for our program, that I understand clearly. Your sample code can be used to state the question in code, but the "Consider this common design:" has to be approaced phrasing the question differently. I wrote my sample code incorrectly. I re-wrote it hoping to grasp the fundamental issue. t_2 & t_3 are redundant - both do the same thing because I have had problems decipering what exactly the compiler is going to do with something.

In the sample code you give neither public void run() nor public void quit() are static. I have figured out that I can make a static variable to communicate broadly across all instances of a class, in your case I think we can say that quit would have to be called from within run - I changed my sample code to reflect the same question coded differently.

Let me rephrase the question thus:

Given the columns metaphor, one instance class is passed to a second instance class in the constructor. (Thread t) in my sample code.

The second instance class then calls some method in the first instance class, which I tried to hang in a no-op loop without getting into the question of whether Java has a no-op, whether one should ever use a no-op [let alone do put a hard spin-lock on it] and other issues which are readily obvious to me because I understand machinery.

I have been stymied trying to do things that are obvious to me, but seem to be optomized away by compilers that are written for a coder that has a different operational burden than mine. The issues are discussed at length by Dov Bulka in Efficient C++: Performance Programming Techniques I say this just because the book gives a clear and well thought-out treatment of the issues by a qualified person and therefore expresses my concerns in a professional way by a qualified person.

The volatile keyword is a classic case. I wasted a lot of time trying to reinvent the wheel on my earlier work on this project in C++ using a proprietary compiler, trying to communicate between two classes before I had achieved reasonable coding skills. All the literature said volatile was an advanced topic.

It isn't, it's just an L-2 writeback .... that's all it is.

What's so difficult about that ?


PS - Yes, start another thread for the other question. I didn't get that one yet.
O.K.
[ January 06, 2007: Message edited by: Nicholas Jordan ]
Nicholas Jordan
Ranch Hand

Joined: Sep 17, 2006
Posts: 1282
Originally posted by Mr. C Lamont Gilbert:
Your thread does not use the thread that is passed to it. So while it can call methods on that other thread, you are not doing so.

You have grasped my question.

I changed the sample code to reflect this.

Please examine and provide opinion.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
[NJ]: Let me rephrase the question thus:

But where is the actual question here? There doesn't seem to be any question at all until "What's so difficult about that?" Which seems to be a side issue, and if you do indeed understand volatile, it's not a question you really need an answer for, is it? What is it you're actually trying to find out?

[NJ]: I changed the sample code to reflect this.

It took a while to spot the changes here - the added doSomething() methods in b and c. There are still multiple compilation errors in the code which indicate problems you would need to fix, but I think we can guess at what was meant here, and how it would be fixed.


"I'm not back." - Bill Harding, Twister
Nicholas Jordan
Ranch Hand

Joined: Sep 17, 2006
Posts: 1282
Originally posted by Jim Yingst:
[NJ]: Let me rephrase the question thus:
But where is the actual question here?


t_2 and t_3 have a reference to instance variable t_1, which is running.

I guess the answer to the question is that t_1 is off and running somewhere else. The fact that t_1 is used in the constructor of t_2 and t_3 makes t.doSomething() in b and c instance t_2 and t_3 a call into the thread of executuion here coded as t_1.start(); in main() - which should not be able to occur, on the basis of a test-case which is contrived to make the constructor call for t_2 and t_3 reference the thread executing in t_1, which should not be executing in main() - which should be impossible because I have blocked the instance with a hard-spin on a no-op.

There doesn't seem to be any question at all until ... Which seems to be a side issue

It is, the purpose of which is to clarifiy that some very well qualified authors will state that some issue is advanced, e.g. an L-2 writeback, when it isn't. The fact that t_2 = new b(t_1); places an instance variable inside the round braces should be explainable in some very simple terms. All the verbosity here was to let posters know I had had trouble with this in the past and what is obviously a retorhical question did not seem to me to lead into other matters.

and if you do indeed understand volatile, it's not a question you really need an answer for, is it? What is it you're actually trying to find out?


[NJ]: I changed the sample code to reflect this.
It took a while to spot the changes here - the added doSomething() methods in b and c.

I realize my mistake last night after I had gone home and gone to sleep. The machine I can post from is six miles away. I was glad to see that someone had spotted it. The fact that it was spotted narrows down exactly where the quesion is.

There are still multiple compilation errors in the code which indicate problems you would need to fix, but I think we can guess at what was meant here, and how it would be fixed.

The code is solely written to illustrate the question in code. I thought putting together an entire program just to psuedo-code the question would make for un-necessary code reading.
Andrew Sancroff
Greenhorn

Joined: Dec 25, 2006
Posts: 10
Nicholas, calling a method of a Thread object does not run the method on a different thread. It runs it on the same thread. Your calls to t_2.doSomething() and t_3.doSomething() are executing on the main thread. There is no magic to calling methods of a Thread object. It's just like calling methods of a non-Thread object.

In your example, you have created t_2 and t_3 but you have not started them so their associated threads aren't even running.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18874
    
  40




t_2 and t_3 have a reference to instance variable t_1, which is running.

I guess the answer to the question is that t_1 is off and running somewhere else. The fact that t_1 is used in the constructor of t_2 and t_3 makes t.doSomething() in b and c instance t_2 and t_3 a call into the thread of executuion here coded as t_1.start(); in main() - which should not be able to occur, on the basis of a test-case which is contrived to make the constructor call for t_2 and t_3 reference the thread executing in t_1, which should not be executing in main() - which should be impossible because I have blocked the instance with a hard-spin on a no-op.


Basically, there is a minor distinction between a thread, and the thread object that represents the thread. So... for t1, the t1 thread is running the run() method of the t1 thread instance, which calls the t1.doSomething() method of that instance. And t2 and t3 objects, which calls t.doSomething(), also calls the t1.doSomething() method of the t1 instance.

This is perfectly valid. Both the t1 and main (which calls t2 instance) threads share the t1 thread instance. They have access to the same instance and static variable, and they both have different copy of local variables as with any method call.

Also note, that if you don't want the two threads to call the t1.doSomething() method at the same time, they should be synchronized.

Henry
[ January 02, 2007: Message edited by: Henry Wong ]

Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Andrew Sancroff
Greenhorn

Joined: Dec 25, 2006
Posts: 10
Another note about your example...

Your constructors for b and c take a Thread parameter but call Thread's no-arg constructor (super()), meaning when you call b.start() and c.start() those threads will do nothing and immediately exit. If you want b and c to call a's run() method when you start them, you need to call super(t) in their constructors.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
[Henry]: Also note, that if you don't want the two threads to call the t1.doSomething() method at the same time, they should be synchronized.

Synchronized on t1, right? If they were merely synchronized methods they would each synchronize using a different instance as monitor, which would not prevent them from simultaneously calling t1.doSomething(). But really, there are too many details left to the imagination for us to meaningfully discuss what would happen anyway, I think.
Nicholas Jordan
Ranch Hand

Joined: Sep 17, 2006
Posts: 1282
Originally posted by Andrew Sancroff:
Nicholas, calling a method of a Thread object does not run the method on a different thread. It runs it on the same thread. Your calls to t_2.doSomething() and t_3.doSomething() are executing on the main thread. There is no magic to calling methods of a Thread object. It's just like calling methods of a non-Thread object.

In your example, you have created t_2 and t_3 but you have not started them so their associated threads aren't even running.

I seem to have generated quite a bit of interest. This machine I work on is remarkably clumsy and rather than make several blunders trying to fix code and so on [along with examining what the other posters have to say] it sounds like you have narrowed down what I am tryihg to ascertain:


Yes, I called .doSomething() in main, but I used the dot operator on an instance variable. IOW - the compiled " bits and bytes " runs:


That's what your answer says ,correct ?

The way I intended to code the problem is backwards from what I understand you are telling me.

Let me examine all the replies, possibly recoding or something - but at least this isolates the question for all posters.
In your example, you have created t_2 and t_3 but you have not started them so their associated threads aren't even running.

That is intentional. Using the columns down the page metaphor, o.k. one point in the code can access a place somewhere else on the column {nomenclature is fun, isn't it :roll: } The run() and the .doSomething()'s of t_1 should be in the second column - all of which if we can get to the .doSomething() from the second and the third column, while t_1 is hung in run,.....

Well let's just say that would   really   interest me and more than justifiy my posting the question.
[ January 02, 2007: Message edited by: Nicholas Jordan ]
Nicholas Jordan
Ranch Hand

Joined: Sep 17, 2006
Posts: 1282
Originally posted by Andrew Sancroff:
Another note about your example...

Your constructors for b and c take a Thread parameter but call Thread's no-arg constructor (super()), meaning when you call b.start() and c.start() those threads will do nothing and immediately exit. If you want b and c to call a's run() method when you start them, you need to call super(t) in their constructors.


Oh, brother - I'm glad I'm getting hit by masters.

That would be a real sneaker waiting to gotcha me somewhere later.
Nicholas Jordan
Ranch Hand

Joined: Sep 17, 2006
Posts: 1282
Originally posted by Jim Yingst:
[Henry]: Also note, that if you don't want the two threads to call the t1.doSomething() method at the same time, they should be synchronized. .... Synchronized on t1, right? ....


I put some synchronized keywords in my discussion draft class Alice, as defensive coding. They were not needed due to some simplifications made for the sake of prototyping efficiency. The question narrowly involves something I read in the book, recognizing it as a potential gotcha.

I cannot do an animated cursor, so lets try this:

As the execution drops into the round braces, things may happen that are the subject of compiler science. There are no other issues involved at this time, other than how the resultant t variable is compiled in the {} execution body of the method.
Nicholas Jordan
Ranch Hand

Joined: Sep 17, 2006
Posts: 1282
Originally posted by Henry Wong:

Basically, there is a minor distinction between a thread, and the thread object that represents the thread. So... for t1, the t1 thread is running the run() method of the t1 thread instance, which calls the t1.doSomething() method of that instance. And t2 and t3 objects, which calls t.doSomething(), also calls the t1.doSomething() method of the t1 instance.

This is perfectly valid. Both the t1 and main (which calls t2 instance) threads share the t1 thread instance. They have access to the same instance and static variable, and they both have different copy of local variables as with any method call.

Bear with me, I tried to block t_1.doSomething() so that - for discussion purposes, to isolate the question - the t_1 run method never returns.

What you are telling me is that although t_1 is " run()'ning " ... the .doSomething() methods OF THAT INSTANCE [ hollering for clarity, not combativeness ] can, will and do .....

Oh, I think I get it. It's when we place a run() method in an instance and call it from start() - that 'object' disappears and becomes an un-named [anonymous] variable. That contradicts the notion that the named variable is a reference to the object, and if I have hung it for purposes of illustrating my question, then that reference can never enter the .doSomething() bit pattern because of the columns down the page metaphor.

It's this sort of deep question that caused me to make the remarks about:
...compilers that are written for a coder that has a different operational burden than mine.

Let me rest on this for the moment, so that you may examine my efforts to wrestle with the matter.


Also note, that if you don't want the two threads to call the t1.doSomething() method at the same time, they should be synchronized.
It is my intent to narrowly isolate a point that I read in the book [as given in the opening of the post] - I have coded this protyping version so that there are no synchronization issues at this time.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18874
    
  40

Bear with me, I tried to block t_1.doSomething() so that - for discussion purposes, to isolate the question - the t_1 run method never returns.

What you are telling me is that although t_1 is " run()'ning " ... the .doSomething() methods OF THAT INSTANCE [ hollering for clarity, not combativeness ] can, will and do .....

Oh, I think I get it. It's when we place a run() method in an instance and call it from start() - that 'object' disappears and becomes an un-named [anonymous] variable. That contradicts the notion that the named variable is a reference to the object, and if I have hung it for purposes of illustrating my question, then that reference can never enter the .doSomething() bit pattern because of the columns down the page metaphor.


Just think of a thread object as merely a java object that is used to represent a thread. You can see properties about or control that thread through the thread object that represents it... In your example:

t1 is an instance of class A, which is a subclass of the Thread class. It is merely an object that is used to represent a thread. When the instance of t1 is created, no threads are created.

When t1.start() is called, the code, which is part of the Thread class, will create a new thread, along with a stack, and everything else that it entails. And then the start() method returns.

This new thread that is created by the start method, will initialize, and eventually call the t1.run() method. You now have a new thread running in parallel to the main thread (which is running your main method), running code in the run() method of the t1 instance.

Henry
Andrew Sancroff
Greenhorn

Joined: Dec 25, 2006
Posts: 10
To help you figure out what's going on, add this method to your code and sprinkle calls to it in various places (like in run() and doSomething()). Requires Java 1.5 (for getStackTrace()). Tells you where you are in the code and what thread is executing it.


[ January 02, 2007: Message edited by: Andrew Sancroff ]
[ January 02, 2007: Message edited by: Andrew Sancroff ]
Nicholas Jordan
Ranch Hand

Joined: Sep 17, 2006
Posts: 1282
Originally posted by Andrew Sancroff:
To help you figure out what's going on, add this method to your code and sprinkle calls to it in various places (like in run() and doSomething()). Requires Java 1.5 (for getStackTrace()). Tells you where you are in the code and what thread is executing it.

Okay, got it to compile - but I am in over my head so let me put it up before I hang my box.

Nicholas Jordan
Ranch Hand

Joined: Sep 17, 2006
Posts: 1282
Originally posted by Henry Wong:
You now have a new thread running in parallel to the main thread (which is running your main method), running code in the run() method of the t1 instance.


Huh ?..... do what ?

If it is running in parallel, which to me says the JVM can assign it to whatever processor it wants to [and I have figured out to leave that decision to the JVM] then the main() thread - illustrated using the colunmns metaphor - is not going to return where as main()in the t_2.where(); call in main() - it will show up as being in the T_2 column.

If not, then it is really worthwile for me to have stopped to look at this.

[there is no neutral smiley - sometimes the cool fits here]
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18874
    
  40

If it is running in parallel, which to me says the JVM can assign it to whatever processor it wants to [and I have figured out to leave that decision to the JVM] then the main() thread - illustrated using the colunmns metaphor.


In all but the really old JVMs, the threading is dispatched to the underlying threading system of the operating system. This means that different threads, running in your program, indeed can, and do, run in parallel on machines with more than one processor.

On machines with only one processor, obviously the threads have to share the processor, but how they share the processor is determined by the operating system. The JVM merely have certain controls like priority, which is configured to map to an equilvalent priority in the OS.

In the really old JVMs, definitely prior to Java 1.2, it used a user level threading system -- meaning that the JVM internally time-slice the threads. These obsolete JVMs also isn't capable of using all the processors as the OS merely see it as a process with only one thread.

Henry
Nicholas Jordan
Ranch Hand

Joined: Sep 17, 2006
Posts: 1282
Originally posted by Henry Wong:


In all but the really old JVMs, the threading is dispatched to the underlying threading system of the operating system. This means that different threads, running in your program, indeed can, and do, run in parallel on machines with more than one processor.

Henry

O.K. - but about two times an hour I have to deal with the equivilant of someone not making the access synchronized. It sounds like what you are telling me is the the entire JVM/source code/physical device is somewhat simpler conceptually than what I am making it out to be and I can go back to reading Java Threads secure that the worst thing that happens is that we get data corruption. [multi/uni-processr]

I.O.W. - we do not get runaway conditions, hung main()'s and so on. Basically I cannot place coding methods in either class, thinking the failure will occur there. All I can do is look out for the problem as described.

Correct ?

[additional material: 8:33 AM 1/6/2007 ]

If I ask my question correctly, everyone asks "Why would you want to do that ?" I left the where() call in the code that compiled as static, but what happens if we leave it as an instance call as given in the psuedo-code at the front of the post ?
  • - main() hangs, app is blocked, but error is detectable at testing.
  • - undefined, this is what I am really trying to uncover.
  • - code executes, as given, correctly. This is the crux of my question.
  • - a concurrent access exception without semantics visible in java sources.

  • If the sample code given responds one way, we approach reliabilty coding from one perspective ... if it happens another way, we approach from a different frame of mind. It may be fail-fast, it may be testing or it may involve matters outside of computer science ~ but to have an efficient approach in mind I have to understand how the bytecode/JVM/physical device respond to this sequence of instrucitons.

    [ January 06, 2007: Message edited by: Nicholas Jordan ]
    [ January 06, 2007: Message edited by: Nicholas Jordan ]
     
    jQuery in Action, 2nd edition
     
    subject: any thread that has a reference to another thread can execute any method of that othe