Thread.stop() is now removed from modern Android API. From https://developer.android.com/reference/java/lang/Thread#stop(),
Many uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, ...
I suppose that a complete removal of a method must be backed by an alternative of it, both for the many uses where it is replaceable, and for the many other uses where it is not. I am therefore wondering what is the alternative of Thread.stop() that stops a thread where cooperative interruption flags do not work, which is possibly due to e.g. calls of slow 3rd-party functions.
From the articles I've googled and the duplicated SO questions I've read about this issue, I got only two unsatisfactory types of answers:
You should just consider cooperative interruption because it's not stupid.
Thread.stop() is now gone for whatever reason so just forget it.
I would appreciate a lot if you could either provide a functioning alternative of Thread.stop() or explain the rationale behind removing it despite the legitimate use cases depending on it, where "legitimate" implies nonexistence of any synchronization and locking issue.
Thanks in advance.
There is no "modern" alternative. The old alternatives are still the only ones. Why? Because this is fundamentally an unsolvable problem1 ... if the threads are not cooperating / checking for thread interrupts, or if they unable to correctly deal with a thread interrupt.
For the record, the technical reasons that Thread.stop() is unsafe include:
It breaks mutual exclusion locks help by the thread being stopped. This may leave the object that was locked ... or other objects ... in an inconsistent state.
It may result in broken inter-thread signalling. For example, if a thread is expected to notify a condition variable, and it gets stopped before this happen, then other threads may be stuck forever waiting for a notify that never arrives.
If has said that, issues such as the above can in theory be addressed by application code on a case-by-base basis. For example, if you were using stop() you could catching ThreadDeath in all of the necessary places, take remedial action and then rethrow it. But to borrow someone else's words, "it would be insanely messy".
I'm sorry if you think this is all unsatisfactory. But this is life. If you cannot write your threads to be cooperative, and you need them to be killable, run them in an external process, via Process etcetera.
Now ... if we could wave a magic wand and replace Java threads with a CSP-like model of concurrency (and in doing so, eschew state sharing between processes), then the problem goes away. Though now you have to deal with the other problem of what to do with the messages queued up when a process is terminated. But at least that is a tractable problem.
1 - I am asserting this without proof! However, if it was a solvable problem, then you would have thought that Sun or Oracle or Google would have discovered and implemented a solution in the last ... umm ... 25 years. Challenge: If you can come up with a viable implementation model for safely killing Java threads, I expect that certain companies would be willing to offer you a very well-paid job. Especially if they can secure exclusive rights on your patent.
Related
In our Netty application. We are moving all blocking calls in our code to run in a special backgroundThreadGroup.
I'd like to be able to log in production the threadName and the lineNumber of the java code that is about to execute a blocking operation. (i.e. sync File and Network IO)
That way I can grep for the logs looking at places were we might have missed to move our blocking code to the backgroundThreadGroup.
Is there a way to instrument the JVM so that it can tell me that?
Depends on what you mean by a "blocking operation".
In a broad sense, any operation that causes a voluntary context switch is blocking. Trying to do something special about them is absolutely impractical.
For example, in Java, any method containing synchronized is potentially blocking. This includes
ConcurrentHashMap.put
SecureRandom.nextInt
System.getProperty
and many more. I don't think you really want to avoid calling all these methods that look normal at a first glance.
Even simple methods without any synchronization primitives can be blocking. E.g., ByteBuffer.get may result in a page fault and a blocking read on the OS level. Furthermore, as mentioned in comments, there are JVM level blocking operations that are not under your control.
In short, it's impractical if not impossible to find all places in the code where a blocking operation happens.
If, however, you are interested in finding particular method calls that you believe are bad (like Thread.sleep and Socket.read), you can definitely do so. There is a BlockHound project specifically for this purpose. It already has a predefined list of "bad" methods, but can be customized with your own list.
There is a library called BlockHound, that will throw an exception unless you have configured BlockHound to ignore that specific blocking call
This is how you configure BlockHound for Netty: https://github.com/violetagg/netty/blob/625f9d5781ed85bfaca6fa4e826d0d46d70fdbd8/common/src/main/java/io/netty/util/internal/Hidden.java
(You can improve the above code by replacing the last line with builder.nonBlockingThreadPredicate(
p -> p.or(thread -> thread instanceof FastThreadLocalThread)); )
see https://github.com/reactor/BlockHound
see https://blog.frankel.ch/blockhound-how-it-works/
I personally used it to find all blocking call within our Netty based service.
Good Luck
A common advice in Java is to not to let the "this" reference escape during construction of an object and therefore not start any threads in a constructor. But I find myself writing a lot of classes that should start a thread using an executor. According to the common advice, I should write an extra start() method that submits the task to the executor.
But submitting a task to an executor gives happens-before guarantees as documented here. So would it be fine to submit the task in the last statement of the constructor? Or the more general question: is it safe to let "this" escape in the last statement of a constructor if that statement provides happens-before guarantees?
The Answer by Stefan Feuerhahn is correct.
I’ll add the suggestion that embedding an executor service within the class performing the work can be a “code smell”, an indication of weak design.
Generally we want to follow the single responsibility principle in our designs. A class should have a single purpose, and should try not to stray from that narrow specific purpose.
If, for example, a class were written to create a report, that class should know only about that report. That class should not know about when that report should be run, or how often to run the report, or what other code cares about if the report has been run.
Such scheduling of when to run the report is tied to the lifecycle of the app. For one important thing, the executor service must eventually be shut down when no longer needed or when the app is exiting. Otherwise the backing thread pool may continue indefinitely like a zombie 🧟. Your report-generating class should not know about when it is no longer needed, nor should it know about when or why the app is exiting.
Another aspect of the issue is that configuring an executor service involves knowing about the deployment scenario. How much RAM, how many CPU cores, how much other burden on that host machine, all contribute to decisions about how to set up the executor service(s). Your report-generating code should not have to change because of changes to your deployment situation.
The report-generating class should not know anything about the calling app’s lifecycle, not know anything about the executor service. The report-generating app should know nothing more than how to generate that one report. Some other place in your code, perhaps some report manager class or your app’s lifecycle orchestration code, should handle how often and when to run the report.
Yes, this is safe, because the statement providing happens-before guarantees will make sure all fields are correctly initialized visible to other threads. One caveat is that a subclass could ruin this safety so its better to make the class final. But, as Holger pointed out, even then an additional constructor delegating to the one that started the thread could harm safety.
The general advice "don't let this escape from the constructor" exists mainly because it is easier and thus less error prone to follow this rule then to keep all nuances in mind (like subclassing).
Summary
From my studies, I don't remember that a concept such "uninterruptible block" exists, and I did not find it either with a quick Google search.
Expected answer
yes, it does exist, and the proper term for that is ... (in this case, it would be nice, if someone could explain me, why it does not exist in Java)
no, it does not exist, because ...
Definition
By "uninterruptible block", I mean a section of code, in a multi-threading context, which, once starts execution, cannot be interrupted by other threads. I.e., the CPU (or the JVM), won't run any other thread at all, until the "atomic block" is left.
Note, that this is not the same as a section marked by lock/mutex/... etc., because such section can not be interrupted only by other threads, which acquire the same lock or mutex. But other threads can still interrupt it.
EDIT, in response to comments It would be fine also, if it affected only the threads of the current process.
RE. multiple cores: I would say, yes, also the other cores should stop, and we accept the performance hit (or, if it is exclusive only for the current process, then the other cores could still run threads of other processes).
Background
First of all, it is clear, that, at least in Java, this concept does not exist:
Atomic as in uninterruptible: once the block starts, it can't be interrupted, even by task switching.
...
[this] cannot be guaranteed in Java - it doesn't provide access to the
"critical sections" primitives required for uninterruptibility.
However, it would have come in handy in the following case: a system sends a request and receives response A. After receiving the response, it has max. 3 seconds to send request B. Now, if multiple threads are running, doing this, then it can happen, that after receiving response A, the thread is interrupted, and one or more threads run, before the original thread has the chance to send out request B, and thus misses the 3 seconds deadline. The more threads are running, the bigger the risk that this happens. By marking the "receive A to send B" section "uninterruptible", this could be avoided.
Note, that locking this section would not solve the issue. (It would not prevent the JVM, from e.g. processing 10 new threads at the "send request A" phase, right after our thread received response A.)
EDIT: Re. global mutex. That would also not solve the issue. Basically, I want the threads to make Request A's (and some other stuff) simultaneously, but I want them to stop, when another thread received Response A, and is going to make Request B.
Now, I know, that this would not be a 100% solution either, because those threads that don't get scheduled right after receiving response A still could miss the deadline. But, at least, those who do, would for sure send out the second request in time.
Some further speculation
The classic concurrency problem a++ could be simply solved by uninterruptible { a++; }, without the need for locks (which can cause dead-lock, and, in any case, would probably be more expensive in terms of performance, than simply executing the three instructions required by a++, with a simple flag, that they must not be interrupted).
EDIT RE. CAS: of course, that's another solution too. However, it involves retrying, until the write succeeds, and it is also slightly more complex to use (at least in Java, we have to use AtomicXXX, instead of the primitive types for that).
I know, of course, that this could be easily abused, by marking large blocks of code as uninterruptible, but that is true for many concurrency primitives as well. (What's more, I also know, that my original use case would be also kind of an "abuse", since I'd be doing I/O in an uninterruptible block, still it would have been worth at least a try, if such concept did exist in Java.)
The prevailing religion of Java today heavily forbids the use of the stop() instance method on a Thread[1] [2] [3]. It's marked as Deprecated in the official documentation, with a message that begins with:
This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior. [...]
There is even a whole article supplied that goes into further detail. (Especially that ThreadDeath is silent when it gets to the top, and even if you guard against it, you can't guard against Thread.stop(Throwable t) anyway.)
In general, I agree with what that article is worried about, and with the answers to the related question on StackOverflow — in almost all the use cases in the world there is a much better way than stop(). But not all.
Here is a use case that I'm struggling to think of a better way for. I invite your suggestions.
Use case
I'm working with an interactive console running on top of Java, that allows the user run arbitrary Java statements and Python functions that call Java, in an interactive interpreted way. (See Jython console for screenshots.)
Now, the user can write arbitrary functions. Some of them might call Java methods that result in infinite loops that print a lot of output, almost saturating the system, so that it becomes painfully slow to respond.
When the user messes up like this, I need to give them a chance to kill the thread (using a button), and salvage the remainder of the work that they have produced in their session and stored in local variables.
If calling interrupt() on the thread fails, (e.g. if it never goes into waiting state while stuck in its infinite loop), then we are faced with two options that I can see: (1) kill the application outright or (2) use stop() on the bad thread, and let the user salvage whatever is left that hadn't been corrupted.
Yes I know that some objects may have been damaged and won't work properly. But we're talking about salvaging anything that may have been left in a valid state (which is probably pretty much everything, except one or two things).
Can anybody see any problems with this reasoning? And if this turns out to be a valid use-case, then does it mean the method shouldn't be deprecated :) ?
Calling Thread.stop() is a bad idea. End of story.
It may work in practice but you sacrifice most of the JVM's concurrency guarantees in the process. Your whole program is essentially running undefined behavior. It isn't simply the thread or the data in the thread that may become corrupted, but any part of the JVM that happens to be in a vulnerable state when the thread is killed.
It sounds like you're looking for someone to confirm that your use case somehow avoids the risks to the JVM. It doesn't, so you're not likely to get such a confirmation. If you don't see issues more power to you, but don't be surprised when it fails in inexplicable or dangerous ways.
As Peter Lawrey suggests you should be running this untrusted code in an isolated JVM, where the OS's process management can support killing resource-hogging processes. If you can't do that because you're passing around strange resources like open file descriptors that is your problem.
The Semaphore class overview in developer.android.com looks pretty good - for those who are already familiar with the concepts and terminology.
I am familiar with some of the acronyms and other jargon there (e.g. FIFO, lock, etc.) but others such as permits, fairness and barging are new to me.
Can you recommend a good online source for explaining these concepts? (I can probably figure out what permits and fairness are but barging is an unknown at this point).
EDIT: After receiving the two answers below, I realized that I need a refresh on semaphores (to re-acquire() terminology). I found the following resources to be useful:
Semaphore_(programming)
Introduction to Semaphores by
Dr. Richard S. Hall
http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html
http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Semaphore.html
This is an excerpt from what is considered one of the seminal works in java concurrency you should check it out.
http://my.safaribooksonline.com/book/programming/java/0321349601/explicit-locks/287
Hadn't come across these myself, but thought I'd research and summarise my findings as it's better to in-line answers than link externally (although, yes, the OP is after recommending reading):
permits are the number of concurrent accesses allowed to the semaphore-protected code. Although often semaphores are simple Mutex's, it is sometimes desirable to have more than one thread touching code. This is similar to phoning a call-centre, where there's one phone number connected to 8 lines/operators.
fairness is when a semaphore is made available to requesters in strict order of who requested first. Staying with the call-centre analogy, this means the on-hold queue is a strict FIFO.
barging is essentially an out-of-band request, that puts a thread to the top of the queue for a semaphore. The analogy is where preferred customers (or internal calls) go to the top of a call-centre queue, rather than waiting their turn.
If neither fairness nor barging are specified, then it's within spec to grant access to the most recent request, depending on timing of context switches. The 'phone analogy is a call to a company switchboard/reception, where even if calls are on hold waiting for answer, you may get lucky and ring between one call ending and another call being taken off-hold.
Let me know through comments if I've got this wrong, and I'll fix / cw my answer.