Win a copy of Murach's Python Programming this week in the Jython/Python forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Failure mode of two reference calls to one thread  RSS feed

 
Nicholas Jordan
Ranch Hand
Posts: 1282
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[NOTE: since putting this up originally, it has become apparent that the post is titled incorrectly. In the post by me Sunday, January 14, 2007 6:02 PM the basis for the work is correctly elucidated, but the entire thread of discussion was driven by intrinsics consequent to repeated failures by contemporary operating systems, a matter discussed professionally in the work cited in the post of 1.14.07 ]


Consider the second instance call in main(), which if this code does what I think it does, presents the question marked as: "what happens here ?"   (in the comments for main)  
  • - 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 instructions.

    [ January 12, 2007: Message edited by: Nicholas Jordan ]
    [ April 29, 2007: Message edited by: Nicholas Jordan ]
     
    Ilja Preuss
    author
    Sheriff
    Posts: 14112
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Nothing special happens. In fact, that t_2 is a Thread, or that you passed t_1 as the runnable, has no impact at all on the direct method call to doSomething.

    There seem to be some basic misunderstandings on how threads work here, so I'm moving this to our Thread forum...
     
    Marc Peabody
    pie sneak
    Sheriff
    Posts: 4727
    Mac Ruby VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I don't think b's doSomething method has visibility to t.
     
    Chris Hurst
    Ranch Hand
    Posts: 443
    3
    C++ Eclipse IDE Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    .. also shouldn't t be a member of b of type class A ... maybe .. :-)

    I think possibly I see the direction your heading (maybe, sorry if I have the wrong end of the stick :-) )

    Apologies if this confuses more than helps ...

    I think the trick to understanding this better is to realise that doSomething in 'A' could be declared static in this case if it couldn't i.e. you used a member variable the problem can be different (or you used a static member of A which is equivalent to a global memory write). So doSomething can be thought of as just a procedure, a definition of instructions two threads are reading at the same time, each thread has its own stack neither visible to the other, you can forget all about objects in this case.

    i.e. doSomething can just be the equivalent of a procedure hidden in the namespace of A a C++ compiler might name mangle it into A__doSomething (actually the non static version would have the same name but the first parameter would be the object type (the hidden this pointer but you don't use a this pointer)) ( this is the kind of thing you have to know if you do JNI :-( )

    Basically if your happy with that model then it should be obvious that all doSomething's memory accesses writes are local to the stack of the thread executing i.e. A can't see B ... so no problem from that threading point of a view not going to comment on the algorithm, recursion depth etc. etc.
    Note again if doSomething used a class static that would be the equivalent of a global memory write and then thread A could see B but again you don't do this.
     
    Jim Yingst
    Wanderer
    Sheriff
    Posts: 18671
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Chris hit the core of what I think you're asking about, Nicholas. If the threads don't share any data (and they don't, here) then they don't interact in any way. In this case, after we fix the compilation errors in class b (which appears unnecessary anyway), both threads (the main thread and t_1) will throw a StackOverflowError. I don't know if that's what you were trying for or not. Neither thread will be affected by the error thrown by the other thread.
    [ January 12, 2007: Message edited by: Jim Yingst ]
     
    Nicholas Jordan
    Ranch Hand
    Posts: 1282
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Ilja Preuss:
    There seem to be some basic misunderstandings on how threads work here, so I'm moving this to our Thread forum...

    Correct, I have worked on this before - I am still digesting the replies. By a quick look, it appears that you are grasping what I am struggling to get a firm grip on.

    It is  : the full and complete comprehension of the failure mode  : that I am singularly concerned with. As you note that:
    Nothing special happens.

    and the intervening class with a direct call to doSomething could have been eliminated entirely - it may reveal my thinking to note that I could have made t_1 call doSomething() directly in main() with the same effect.

    The fact that I chose not to, in fact in the uncorrected posting my code unconciously eliminated the t.doSomething() in class b, shows that I was attempting to direct attention to the question [edit: at the point of putting class b in the execution path] of whether the compiler would recognize this fact and collapse the call to the equivilant of making the call from main.[edit: In so doing, I was trying to direct attention to the fact of making a second instance call in an instance that was already running.]

    What I have tried to do, with limited skills, is keep the t_1 instance busy, busy, busy - by hanging it in a crude beginner's attempt at Fibonacci. I could as well coded: while(true)continue; The thread main() then goes to the next statement: (revised) t_1.doSomething(0Xffffffff); which concerns me because to me it looks like an obvious failure, waiting to ruin a weekend.

    What I understand you telling me is be though it may that t_1 is busy, the execution of the JVM just merrily executes t_1.doSomething(), being oblivious to the fact that t_1 is busy right now, and code execution continues without failure nor data corruption, except for the need to address concurrency issues. IOW - my question is   not   synchronize(this) and related issues, it's   how   you can call into an instance that is already busy in a loop.

    This would violate common-sense notions of a Thread of execution, and if such is true makes it worthwhile that I examined the code-execution-path rigourously.

    That, sir, is absolutly the last thing I thought the JVM would do.

    For obvious reasons.
    [ January 14, 2007: Message edited by: Nicholas Jordan ]
     
    Nicholas Jordan
    Ranch Hand
    Posts: 1282
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Marc Peabody:
    I don't think b's doSomething method has visibility to t.

    [edit: this posted code doesn't either - b would have to extend a]


    [ January 14, 2007: Message edited by: Nicholas Jordan ]
    [ April 29, 2007: Message edited by: Nicholas Jordan ]
     
    Nicholas Jordan
    Ranch Hand
    Posts: 1282
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Chris Hurst:
    Apologies if this confuses more than helps ...

    I would much rather dig through a hundred responses leading to unproductive but well meaning speculation than I would to risk one in one hundred that I might have uncovered a failure mode.

    As soon as I get done, I will be reading Practical Cryptography by Niels Ferguson and Bruce Schneier, John Wiley & Sons, 2003 .... they repeatedly give good grounds (no pun intended) for you not to be shy about jumping in with your contributions.

    Between them, they have contributed over one hundred papers to the scientific literature.

    I invite your assistance at any time.

    ...doSomething in 'A' could be declared static

    ... it should be obvious that all doSomething's memory accesses writes are local to the stack of the thread executing i.e. A can't see B ... so no problem from that threading point of a view ... etc. etc.

    Correct, but it is the problem case that I am trying to uncover !

    I can figure all this out, it is the failure mode that I am trying to probe. IOW - What happens if ....(some coder next summer fails to do the things you are discussing. )

    Note again if doSomething used a class static that would be the equivalent of a global memory write and then thread A could see B but again you don't do this.


    Correct, because of trying - point out any failures to do this - trying to make the call a call into an instance, which would also be a thread that is already running, which would make no sense - which is why I went from Threads and re-posted in Testing .... it is not so much a thread issue per se as it is a failure mode probe so that I know what happens in this coding error.

    It just looks to me, as a mechanic by nature, that the entire JVM goes into a undefined state, which is the hardest to detect by testing. Ferguson & Schneier are   HIGHLY, HIGHLY   critical, in their book, of the industry for negligence to look for failure modes, such as I am doing here, and choose the strongest words I have ever seen in professional work to characterize the nature of the industry generally as weakness in the core for not looking for this type of thing.

    [ January 14, 2007: Message edited by: Nicholas Jordan ]
    [ April 27, 2007: Message edited by: Nicholas Jordan ]
     
    Nicholas Jordan
    Ranch Hand
    Posts: 1282
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Jim Yingst:
    Chris hit the core of what I think you're asking about,

    Chris works very hard, and professionally to show me the correct way to do it.

    It's the weekend ruiner, because of failure to do the things being discussed that I am trying to understand.

    In one failure mode, we try to salvage the clients data. In another, we just exit to avoid doing any real, further mistakes.

    In some cases, we either try to roll-back or destroy data that might be corrupted before it propogates.

    ... will throw a StackOverflowError....

    Contemporary compilers are remarkable for their deftness at recognizing tail recursion, and producing compiled code that will not produce a StackOverflowError, the function - as I tried to write it - will produce some type of Math overflow error. I would have coded while(true)continue; had I have thought that would not have distracted from the question.
    [ April 29, 2007: Message edited by: Nicholas Jordan ]
     
    Ilja Preuss
    author
    Sheriff
    Posts: 14112
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Nicholas, I'm not sure whether I'm able to totally follow you, but it seems to me that you might still be misunderstanding something basic:

    It's not the "instances" that are busy, it's the *underlying threads*.

    All that happens when you call t_1.start() is that the Thread implementation creates a new OS thread and executes the run() method on that thread. There doesn't happen anything more special on t_1.

    So even when you'd call



    on the main thread, there wouldn't be a "failure mode" that you seem to be imagining. The run() method simply would be executed twice, concurrently - once on a mew thread, once on the main thread.

    I hope that makes it a little bit more clear...
     
    Nicholas Jordan
    Ranch Hand
    Posts: 1282
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Ilja Preuss:
    Nicholas, I'm not sure whether I'm able to totally follow you, but it seems to me that you might still be misunderstanding something basic:

    Not really, though it may sound like it. From the remainder of your reply, it is readily apparent that you grasp the arena in which my question is solved. What will not be totally followed is that I realize the machine works on threads, and once I get the mechanics clear in my mind - the first thing I will do is code in checks and cross-balances to detect a coder that comes along later and uses the tools the other posters are trying to convey to me.

    It's not the "instances" that are busy, it's the *underlying threads*.

    Correct. Consider my first attempt at re-coding my question:

    .... there wouldn't be a "failure mode" that you seem to be imagining. The run() method simply would be executed twice, concurrently - once on a new thread, once on the main thread.

    Yes, it is - but not the way you are constructing it. Ferguson & Schneier discuss this in their work (what I am attempting to do here) The faliure I am trying to understand arises from the coder who looks at the code, then codes the sample code I provided at the front of the post. Now that I undersand what it is I am trying to ask, I can achieve much of my quesion's goals:

    Given a Thread, the only way to clearly and uniquely identifiy that thread from the machine's viewpoint is to call: Thread.currentThread();, correct ? If so, the above tool will be placed in production code in my project after comments by others are accepted.

    Note that public boolean synchronized check(Thread t){ is synchronized. This method call as written contrasts to an earlier help attempt citing where(); from J.D.K.- 5 as answer to the question.

    As given, this method attempts to check that vars have not been modified by some other thread during the function call. If so, we have a coder on the project somewhere who does not have any business on my team - the type of coder that looks at the source code and thinks the source tells all. I then pair that coder up with my Social Engineer and tell him to find out how this guy got in.
    [ April 29, 2007: Message edited by: Nicholas Jordan ]
     
    Chris Hurst
    Ranch Hand
    Posts: 443
    3
    C++ Eclipse IDE Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    ok ...

    First reading your previous comments, I suspect



    will not give the answer I think you are expecting as it will be the parent thread i.e. the thread that created the object representing the new thread not the one the new object will represent i.e. in your case probably the main thread not the ThreadLocator thread. I suspect you mean to store the new running thread and have certain methods for its use only ??, to do this call it from the first line of run.

    At the moment your checkThread checks if the currently executing thread created this thread, its possible you intended this behaviour but I suspect you don't. I think your now trying to add methods that can only be called from one thread. Note threads often have methods that should be called from other threads e.g. things like stop () for inter thread communication e.g. thread A wants thread B to stop so it calls the stop on thread B but its actually still executing in thread A which can be confusing .

    I have a suspicion now your trying to write the equivalent of an assertion on methods to say only execute if your executing in the thread represented by the object to which the method belongs.

    I'm thinking now from your origonal question you wanted a doSomething that can only be called from one thread instance ?? but the confusion arose as in general there is nothing wrong with having a method called from different threads (if you know what your doing)

     
    Nicholas Jordan
    Ranch Hand
    Posts: 1282
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Chris Hurst:
    ok ...


    Thank you, I needed that. After deep contemplation, I figured out what my misunderstanding is:

    "code executes, as given, correctly."

    I was so used to having consumer-grade operating systems hang and so on that it did not occur to me that thread runners would run the object, and even if there is a hornet's nest of them ... the ONLY issue is/are concurrency issues.

    Examining your code, it appears to me that the constructor is run in main() - therefore will return the same thread i.d. as main() will. After run() is called, you label the diagnostic as in run method, and therefore I construct that that call to get thread i.d. will return a different thread i.d. - and therefore I have a tool with which I can track which active instance (?...) in other words a combination of an instance and a thread engine are doingSomething().

    In other words, a very complex field of written code can be written by me and once there is an entry(), it's the same engine all over the place ~ until I call run on something. At that point, we have two engines driving the same code page (sorry, nomenclature challenges disambiguation skills) - and very literally, one of them can go off into another class written in another code module (file) and with little work, we really have a complex field that invites syncronization to prevent undefined behaviour.

    This question follows immediately from the one I posted, and your illustration provides needed clarification that will allow me to construct my entire project confidently - if one can use that word after reading the practical disucssion by Niels Ferguson and Bruce Schneier.

    [ January 17, 2007: Message edited by: Nicholas Jordan ]
    [ April 27, 2007: Message edited by: Nicholas Jordan ]
     
    Nicholas Jordan
    Ranch Hand
    Posts: 1282
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Chris Hurst:
    its possible you intended this behaviour but I suspect you don't.

    I did. After contemplation - it is exactly the behaviour I intended.

    Additionaly clarity was brought to me by considering the problem of unique user-id generation on a busy server.

    By the time a getUserID() gets called, some other thread may - and on a busy server likely will have - changed the user id from " what you think it is " to some other value. Hence, establishing a user-id must be synchronized or in some other way written into the session in a manner which addresses this failure mode reliably.

    IOW - the machine doesn't fail, the coder does.
     
    Mr. C Lamont Gilbert
    Ranch Hand
    Posts: 1170
    Eclipse IDE Hibernate Ubuntu
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thread is a class just like any other class. A thread of execution is a different thing. You can start a new thread of execution with Thread#start. You can create a new Thread object with new Thread(). They are not the same thing and not related at all.

    If you are not calling Thread#start, then you are just calling an ordinary method which will be have like any other method on any other class.
     
    Nicholas Jordan
    Ranch Hand
    Posts: 1282
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Mr. C Lamont Gilbert:
    ... They are not the same thing and not related at all.....

    This gets to the central point. For some, thinking about threading resembles fifteen ways to stack a cat. USUALLY, such efforts fail.

    Re-reading the entire post, all the way through confirms that I had posted (originally) exactly the question that was on my mind, and Ilja Preuss answered my question effectively. I had *assumed* the machine would fail. Chris's expectation that:
    First reading your previous comments, I suspect

    will not give the answer I think you are expecting

    is the same sort of glue that makes drilling down to the core of the question difficult. In that you are generous enough to poiint out that:
    ...they are not the same thing and not related at all

    consider the sample posted by me Sunday, January 14, 2007 5:44 PM

    What this does, I have no idea .... but I was trying to get the machine merrily driving one instance with two processors.

    This is really close to what you are addressing, and since I have resolved my original question effectively, it appears productive to examine that I had blunderd in this code in that the doSomething(n) in class a would not even be visible to class b - largely an ultimate consequence of studying the matter which you direct.
    We could:

    I have read since posting that start() can only be called once on an instance - we would have to implement runnable to get this idea into compilable code, raising the question of exactly how I would write my sample code correctly. IOW - how exactly would one get multiple threads of execution driving one instance .... it may sound inane, I have long-term reasons for resolving this, it has to do with everyday practicality and is supported by extensive experience in field operations in the real world.

    IOW - it is reliability engineering.

    Assuming that several necessities for the compiler are placed by competent coders b4 using this test class, and furthermore, assuming there are only fifteen ways to stack a cat by the book and no more .... we have here four cats stacked up, some busy processors and hoards of confused onlookers.

    Correct ?

    Please bear in mind it escapes my grasp why some people have difficulty differentiating between instances of a class and processors driving those instances of a class and that I have resolved my original question at the root of this post.
    [ April 27, 2007: Message edited by: Nicholas Jordan ]
     
    Nicholas Jordan
    Ranch Hand
    Posts: 1282
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Marc Peabody:
    I don't think b's doSomething method has visibility to t.

    And I note my re-code doesn't really fix the matter either (I think).

    Then what exactly is passed in a constructor call thus:
     
    Nicholas Jordan
    Ranch Hand
    Posts: 1282
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Chris Hurst:
    (...quote items addressed individually...)


    ... also shouldn't be a member of b of type class A ...


    We may be getting into issues that are beyond the scope of the original question. I made a blunder here in the original coding, which derives from the nature of the problem domain. I was trying to portray a coding where having called a start() on an instance, there would be a second attempt to "run()" or "start()" the "instance"

    Since the orginal time frame of posting the question, I have grasped the idea of an execution of instructions formed be a pattern of electrical impulses in RAM - the original purpose of making a constructor call-chain was to put the "running" in a second class so that I could "start()" the instance twice. The code, as posted, does not effectively portray my underlying question, which should be:

    Failure mode of concurrent execution. Which isn't. Which provides the opportunity to examine your idea here. It is correct, there is no visibility in class b of a method in class a unless that class b extends a ... therefore my original coding of the question - as well as the title of the post - are defective.

    I think possibly I see the direction your heading (maybe, sorry if I have the wrong end of the stick)


    I beleive the Stack a Cat metaphor is more effective than a stick, which only has two ends.

    Apologies if this confuses more than helps...


    It doesn't, it helps by allowing separation of issues.

    So doSomething can be thought of as just a procedure, a definition of instructions two threads are reading at the same time, each thread has its own stack neither visible to the other, you can forget all about objects in this case.


    I thought all threads ran in the same process space, and had visiblity to the vars of an instance. I remember the great relief that came when I figured out how to get a varable visible across file compilation unit boundaries in C++ ... of course it was not long until I was trying to separate them out again, but such matters usually come around again and again to the same mental point and must be resolved until the matter is instinctive while working.

    Effectively dealing with threading issues is not readily apparent from examining source code in Java or any other linguistic.

    i.e. doSomething can just be the equivalent of a procedure hidden in the namespace of A a C++ compiler might name mangle it into A__doSomething (actually the non static version would have the same name but the first parameter would be the object type (the hidden this pointer but you don't use a this pointer)) ( this is the kind of thing you have to know if you do JNI


    Yes, but that does not address the intractability of trying to catch an unforseen coding blunder by an as yet unknown coder who tries to restart a Thread object that has already been run. This construction of your words here returns us close to the original purpose of the post.

    ...Note again if doSomething used a class static that would be the equivalent of a global memory write and then thread A could see B but again you don't do this.


    Well, yes - if they were static. I did not make them static because of .... what the problem here is that anytime anything is hidden, I know from experience to ferret that thing out and get it where it can be seen. I doubt Java will let me get at a hidden this pointer, and even if it did - what would happen if on a team effort there was a well meaning coder who made a code execution path that inadvertently recalled start() on an instance that had already been run ?

    I am sure this entire discussion sounds difficult to to grasp for many people, but about ten times a day I have to deal with the equivilant of someone not examining issues effectively.

    It seems to me we can be effective thus: Explain by explaing why one *wouldn't* ".... do this .... " as in "...global memory write and then thread A could see B but again you don't do this. " IOW - if one did not make it a global, there must be a reason. Why would one make it what C++ calls a this pointer ? (I do not know what that pointer is called in Java, which does not allow pointers in the source code)
    [ April 29, 2007: Message edited by: Nicholas Jordan ]
     
    With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!