File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Threads and Synchronization and the fly likes sleep() vs suspend()  and  stop() vs volatile Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "sleep() vs suspend()  and  stop() vs volatile" Watch "sleep() vs suspend()  and  stop() vs volatile" New topic
Author

sleep() vs suspend() and stop() vs volatile

amit sanghai
Ranch Hand

Joined: Dec 05, 2000
Posts: 231
I am confused between sleep and suspend. It is written in the site "http://java.sun.com/products/jdk/1.2/docs/guide/misc/threadPrimitiveDeprecation.html" that suspend causes deadlock. But sleep is the same thing. So, it should also cause deadlock.
1) The following para is written in the site:
"Thread.suspend is inherently deadlock-prone. If the target thread holds a lock on the monitor protecting a critical system resource when it is suspended, no thread can access this resource until the target thread is resumed. If the thread that would resume the target thread attempts to lock this monitor prior to calling resume, deadlock results".
Does it mean that if the thread that is holding the lock is suspended, before some other thread locks the object it has to call resume().
2) Stopping a thread causes it to unlock all the monitors that it has locked. They have said to use "volatile" variable to indicate that the thread can be stopped.
private volatile Thread blinker;
public void start() {
blinker = new Thread(this);
blinker.start();
}
/*public void stop() {
blinker.stop(); // UNSAFE!
}*/
public void stop() {
blinker = null; // correct
}
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
The critical difference between sleep() and suspend() is that sleep() is static, while suspend() is not. This doesn't sound like a big deal - but what it means is, sleep() is written so that it always puts the current thread (i.e. the thread that called the sleep() method) to sleep. It doesn't require or use any other Thread instance;if you're in thread t1 you can't put another thread t2 to sleep - you can only put yourself (t1) to sleep. When you put t1 to sleep, you need to pay attention to whether t1 is holding any locks which will prevent other threads from functioning. This isn't too difficult to figure out though - you can analyze t1's code to see what synchronized blocks/methods it's inside when sleep() is called.
In contrast, suspend() is an instance method. If I'm in t1 but I have a reference to t2, I can suspend t2:
t2.suspend();
The problem is, I don't really have any way of knowing if t2 was doing something really critical at the time, like holding onto a lock which I need it to release. It's possible I might be able to analyze the code very carefully to be sure this doesn't happen, but it's very difficult, and most people get it wrong. Thus, it's almost always a bad idea for one thread to suspend() another. Instead, the preferred mechanism is to interrupt() the other thread, which is written so that it has less serious consequences to the other thread. In fact in many cases interrupt() won't really do anything, unless the other thread's code is written in such a way as to check for interruptions. Thus, interrupt() is basically a request for the other thread to stop (as soon as it's convenient) rather than a command to stop instantly (which could be trouble if the thread is doing something important.)
Note that a similar problem exists for stop(). You probably won't get deadlock here, since stop() releases locks held by a thread. But this makes it very dificult to perform any required cleanup - you don't know what state objects are in, and as soon as those locks are released other threads may start acting on the objects before you've have a chance to undo changes that were in progress when the thread was interrupted. It can get very ugly.


"I'm not back." - Bill Harding, Twister
amit sanghai
Ranch Hand

Joined: Dec 05, 2000
Posts: 231
Thanks Jim. What is the alternative to stop().
Waht is the function of the "volatile" keyword?
JANARTHANAN SR
Greenhorn

Joined: Oct 06, 2004
Posts: 1
Thank you very much Jim. I got the exact thing what I was searching for. Thanks a lot.
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

Originally posted by amit sanghai:
Thanks Jim. What is the alternative to stop().
Waht is the function of the "volatile" keyword?


"Stop, please"

you put a method on the class that sets a variable. your running thread should check that variable periodically to determine if it should sleep or exit or whatever. So you ask the thread to stop, you dont force it too.

As for the volatile keyword, seems a mistake. I have not yet found an appropriate situation for it....
David Harkness
Ranch Hand

Joined: Aug 07, 2003
Posts: 1646
Originally posted by CL Gilbert:
As for the volatile keyword, seems a mistake. I have not yet found an appropriate situation for it....

The volatile keyword forces every read and write by any thread to synchronized to memory. Thus, it is most often used for fields that are inter-thread flags, as it's used above.

Without the volatile keyword, the loop condition in the run() method -- "while (blinker == thisThread)" -- may not see the change to "blinker" in the stop() method since it happens in a different thread.

You can also force a memory synchronization by using the synchronized keyword, though you should check out the Java Memory Model and Thread Specification (aka JSR-133) if you're writing thread-intensive code.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18824
    
  40

The "volatile" keyword itself is very limited in it usefulness. It is best used for concurrent access to variables (but not long and double). Technically, you can use the synchronized keyword instead, but it is not very efficient to create synchronized setter and getter methods with a single operation in each.

This has been vastly improved with JDK 1.5. The atomic libraries provide similar functionality to volatile variables, but with additional atomic functionality like compare and set, get and set, and increments.

With these atomic variables, you can in theory, remove all synchronization from your program.

Henry
[ October 07, 2004: Message edited by: Henry Wong ]

Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

Exactly Henry. When using volatile you almost always should really be using synchronized methods. And I have yet to find that 'almost' situation.

Why you make long and double exceptions? volatile makes long and double access atomic.


"but it is not very efficient to create synchronized setter and getter methods with a single operation in each." I dont know why you feel this way? Give me an example where volatile works better than synchronization. In the above example it does not. you access to the variable is still unsafe because what if someone tried to stop it even before it was started? or while it was starting? volatile wont protect you.

I know the java memory model very well too.
[ October 07, 2004: Message edited by: CL Gilbert ]
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18824
    
  40

Why you make long and double exceptions? volatile makes long and double access atomic.


Volatile does not make any variables atomic. Volatile forces the JVM to not make a copy (or cache) of the variable, and to directly access them everytime. Access to long and double variables are not atomic because the specification does not require it.

"but it is not very efficient to create synchronized setter and getter methods with a single operation in each." I dont know why you feel this way? Give me an example where volatile works better than synchronization. In the above example it does not. you access to the variable is still unsafe because what if someone tried to stop it even before it was started? or while it was starting? volatile wont protect you.


Not sure what you mean. How do you start or stop a volatile variable?

Henry
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

Originally posted by Henry Wong:


Volatile does not make any variables atomic. Volatile forces the JVM to not make a copy (or cache) of the variable, and to directly access them everytime. Access to long and double variables are not atomic because the specification does not require it.


Access to long and double variables is atomic when associated with the keyword volatile. And this is precisely spelled out in the specification.



Not sure what you mean. How do you start or stop a volatile variable?
Henry


I was referring to starting and stopping a thread which is what this forum thread was about.

For instance


If these 2 methods are synchronized, all is well. If they are not and the stop method is executed as I indicate above, you have a NPE.
[ October 08, 2004: Message edited by: CL Gilbert ]
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18824
    
  40

Access to long and double variables is atomic when associated with the keyword volatile. And this is precisely spelled out in the specification.


You are correct on this one... I guess it has been way too long since I looked at the specification. I do remember a hallway discussion on this many years ago though. Maybe I should have paid attention...

I was referring to starting and stopping a thread which is what this forum thread was about.


Well, at this point of the discussion, it was detoured to the value to volatile variables. And I was just pointing out that for simple concurrent access it is better to use volatile than to create synchronized setters and getters.

For instance, declaring x to be volatile and having "x=y", may better than creating a synchronized setX() method and having "setX(y)". You save on the method call, synchronization, and return. This may be important if the variable is used in a loop, which could mean that you save on multiple calls to getX().

Sorry for the confusion...
Henry
[ October 08, 2004: Message edited by: Henry Wong ]
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

I understand you point Henry and agree with you. But strangely in all my years of multithreaded programming I have never been able to use volatile in place of synchronized so to speak. I have begun to believe that its just not possible.

I understand your example of having "x=y", but I would prefer a real life one because I just have never seen a real functional example.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
[OK, I know this discussion was a few months ago, but I missed it; sorry. And CLG and Henry still seem to be around, so...]

Well, historically volatile has been rather unreliable. E.g. most JVMs did not implement the guaranteed atomicity for volatile longs or double, prior to 1.4 I believe. (As you may recall from this thread.) And even with full compliance to the specs, the original specs leave several loopholes with respect to reordering of operations - which meant that volatile was often too weak to really be useful. But JSR 133 changes this, making volatile stronger than it was. So even though up to now you haven't seen any good examples where volatile was really appropriate, I think you are more likely to see them in the future.

In fact, one place to look is in the JDK source itself, from src.jar. Grep for "volatile" in the java/lang and java/util directories, for example. JDK 1.4 has a few usages of volatile; JDK 1.5 has more. I haven't investigated them all carefully, but the ones I've looked at seem reasonable usages. E.g. the modCount variable in HashMap, used to detect concurrent modifications. There are a few ways in which this code might fail to detect a concurrent modification, but it will work the vast majority of the time. And the API (inherited from 1.2) specifically allows this. (That is, it may fail to throw ConcurrentModificationException in a case where there was concurrent modification; it should never throw CME if there was no concurrent modification.) Looks like the tradeoff made here was to avoid the overhead of synchronization, at the expense of having a slightly less robust method. For concurrent modification detection, that sounds good to me. If my code has a bug that allows concurrent modification, do I need Sun to detect this for me 100% of the time? I think not - detecting it 99% of the time is good enough. I'm going to run my unit tests more than once anyway. If CME is being thrown 99% of the time, I'll have no trouble detecting it.

Or consider java.util.Scanner, which uses volatile for lazy instantiation of two different Pattern fields. In the past this would've been dangerous, as it was possible for a thread to gain access to a reference to the lazily-instantiated Pattern instance before the constructor had fully formed it. But thanks to JSR 133 this should no longer be possible (I think). The way Scanner.java is currently written, there is still a possibility that boolPattern might be initialized more than once (near-simultaneaously) - but given that Pattern is immutable, I don't see any problem with this. It means that there's a very slight chance that the JVM might do twice as much work as necessary in initializing the field - but the benefit is, each subsequent access avoids the overhead of synchronization, in favor of the lesser overhead of volatile.

Note that although Scanner uses a lax form of lazy instantiation (allowing a chance of multiple initializations), it seems the newly-strengthened volatile can also be used for a safe implementation of double-ckecked locking (finally!):

Though there was already an alternate mechanism for thread-safe lazy instantiation using the class loader:

I believe this only works for static fields though, so the new volatile semantics were needed to allow double-checked locking of instance fields. For statics - well I'm not sure which technique is more efficient ultimately. (Too lazy to test carefully right now.) BarLoader seems more readable to me though. But that depends on the reader knowing that BarLoader won't get loaded until getBar() is called the first time. Neither form is very obvious to a newbie.

Now, one problem in all this is that I haven't yet found a clear statement of whether or not Tiger is expected to fully comply with JSR 133. I think so, given that JSR 133 and JSR 176 are both marked as having their final release on September 30 2004, the same day as JDK 5.0 was officially released. But the text of JSR 176 still seems to refer to 133 as something under development (which was true when 176 was first written - but is it now?). And the relase notes for 1.5 don't seem to mention JSR 133 or the new memory model anywhere. My guess is that yes, 1.5 is officially supposed to follow the new memory model (barring any bugs of course). But it would be nice to see this stated clearly somewhere.
[ November 27, 2004: Message edited by: Jim Yingst ]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
[CLG]: keyword volatile. And this is precisely spelled out in the specification.

[HW]: You are correct on this one... I guess it has been way too long since I looked at the specification. I do remember a hallway discussion on this many years ago though. Maybe I should have paid attention...


Henry may have been thinking of one of two things. (1) Non-volatile longs and doubles do have fewer atomicity guarantees than other non-volatile primitives. (2) For volatile longs and doubles, even though the specs have always guaranteed atomic reads and writes, many JVMs failed to implement this properly. At least up until JDK 1.4, it seems. See the previously-referenced thread here.
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

I totally agree with you Jim. There is always a loophole when you use volatile. If you can deal with less than 100% you can surely use volatile. Probably in high speed environments people are willing to cheat a bit. Perhaps my non-production-ness is showing. I'm not very pragmatic sometimes
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: sleep() vs suspend() and stop() vs volatile