How can I lock a method until an other method is invoked?
public class TestLock{
public void methodIsLockedAfterFirstCall(){
doSomething();
//now lockThisMethod (when invoked, the thread shall sleep)
}
public void methodToDoSomethingAfterTheFirstMethod(){
doSomeOtherThing()
//unlock the first Method?
}
}
Is there something already in Java for this or should I do it some way around ( e.g. Boolean or AtomicLong)?
If you want to build this up from base principles you'd do something like:
private final AtomicBoolean lock = new AtomicBoolean();
public void methodIsLockedAfterFirstCall() {
doSomething();
synchronized (lock) {
while (lock.getAndSet(true)) try {
lock.wait();
} catch (InterruptedException e) {
return; // SEE NOTE 1
}
}
}
public void methodToDoSomethingAfterTheFirstMethod() {
doSomeOtherThing();
synchronized (lock) {
lock.set(false):
lock.notifyAll();
}
}
This code:
Uses a private lock. Locking om something public is only acceptable if you document this behaviour and maintain this behaviour for future versions (or mark your new version as utterly incompatible with the old). As a rule, public locks are an error. synchronizing on this, therefore, is usually wrong. This code locks on a private variable.
This code does not run afoul of JMM issues by using AtomicBoolean.
NOTE 1: InterruptedException only ever occurs if you (or other code running on the JVM) explicitly calls .interrupt() on the thread (it does not occur if e.g. the user hits CTRL+C, or killall YourProcess, or 'end task' in the task manager, or any other way that doesn't involve code running in that VM that calls .interrupt(). What to do? Well, do not just e.printStackTrace(), the usual mainstay of java programmers who no idea what they are doing. What did you want to happen when you write thread.interrupt(), somewhere else in the codebase? Do that. If the notion of 'stop waiting for that second call now' is a sensible idea, then document the behaviour in this method. Here I've chosen to just return (stop waiting), but keep the lock in locked state.
Does not use notify/wait as a mechanism to communicate data; only as a mechanism to communicate when to wait and when to stop waiting. This is generally a good idea, it can be very hard to debug relevant state when that state is captured by 'were you notified or not', and makes it impossible to use the wait(timeout) variant. That's why there is a while loop. Being woken up just results in trying to getAndSet again, which can reuslt in waiting some more. That's a good thing.
Or, use something from j.u.concurrent. Some ideas:
A Lock which the first method locks and the second method unlocks.
A Semaphore doesn't sound right, as .release() will add 1 to the count, always, so if you call the second method whilst the 'lock status' is UNLOCKED, you'd erroneously be adding a permit. You can't do if (semaphore.availablePermits() < 1) semaphore.release(); as that'd have a race condition unless you do this in a synchronized block which kinda defeats the purpose.
There is a lot under the java.util.concurrent.locks and java.util.concurrent packages.
Maybe CountDownLatch is the easier one to use:
private final CountDownLatch latch = new CountDownLatch(1);
public class TestLock{
public void methodIsLockedAfterFirstCall() throws InterruptedException {
doSomething();
//now lockThisMethod (when invoked, the thread shall sleep)
latch.await()
}
public void methodToDoSomethingAfterTheFirstMethod(){
doSomeOtherThing()
//unlock the first Method?
latch.countDown();
}
}
Related
suppose there are 2 threads used in this demo.Suppose increment() code block executes first and acquires the monitor on the current object.does other thread will not be able to execute the method decrement() ? .
can anyone help me understand?
if I ran the application, other thread able to execute non-synchronized method even though is lock on the object hold by thread that sleeps 10000 ms .
package com.learn.threads;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadDemo {
int sharedVariable;
public ThreadDemo(int sharedVariable) {
this.sharedVariable = sharedVariable;
}
public synchronized void increment() throws InterruptedException {
Thread.sleep(10000);
this.sharedVariable++;
}
public void decrement() throws InterruptedException {
this.sharedVariable--;
}
public static void main(String[] args) throws InterruptedException {
ThreadDemo task = new ThreadDemo(0);
ExecutorService incrementExecutorService = Executors.newFixedThreadPool(2);
for (int i = 0; i < 6; i++) {
incrementExecutorService.submit(() -> {
try {
task.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread.sleep(5000);
incrementExecutorService.submit(() -> {
try {
task.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
Thread.sleep(35000);
incrementExecutorService.shutdown();
System.out.println(task.sharedVariable);
}
}
No, it won't.
synchronized on a method is just syntax sugar for wrapping the entire body of the method in synchronized (X) {}, where X is this for instance methods and YourClass.class for static ones. It is a severe design error unless you document the locking behaviour of your class if you do this - anytime you lock on stuff other code could get a reference to (this and YourClass.class are usually public), you need to document this, and endeavour to support what you document in future v ersion.
synchronized interacts with other synchronized blocks on the same reference, and on thatRef.wait/notify/notifyAll() and nothing else. It has zero effect on its own, you always need 2 different threads both hitting a synchronized block, synchronizing on the same thing, or it does nothing useful.
The code snippet as pasted is broken: If some thread calls decrement(), other threads may or may not observe this, as no CBCA relationship is established. Any code that reads sharedVariable needs to lock on ThreadDemo, and the decrement method needs to gain a synchronized attribute.
Note that the job of having an incrementable/decrementable thing already exists: AtomicInteger, you should be using that instead if this is your actual intent (but I'm assuming you wrote this merely as an example).
NB: The java memory model is best understood as an evil coin. Evil in that it is out to mess with you: To have code that works great every time and in all your tests, and the first week you put it live on the production servers, and then just as that important customer gets a demo, it breaks. You must write code such that the VM never flips that coin (or rather, that the results of the flip do not affect your code), and there is no easy way to know that the evil coin is being flipped. Threading is very difficult to get right, yup. Why do you think most multithreaded code out in the real world does all inter-thread communication via a message bus or transactional database? The coin is flipped anytime any code touches any field anywhere, and the result of the coin decides whether the thread uses a local clone copy of that field, or if it reads from the shared copy. Thus, sharedVariable-- might result in a decrement that only your thread can see, or all threads can see, depending on the result of the evil coin. If what your code does depends on the flip, you messed up, and your tests aren't going to catch it. You can avoid the coin flip by establishing a comes-before relationship between sharedVariable-- and whatever cod reads sharedVariable. synchronized is one of a few ways to establish such a relationship. Search the web for 'java memory model' 'synchronized' for more info - but note that this is very complex stuff.
Please see the code below:
private static boolean flag=true; // main thread will call flag=false
private final static Object lock=new Object(); // lock condition
public static void thread1(){
while (flag){
synchronized (lock){
// some work
}
}
}
public static void main(String[] args) throws Exception {
Thread t1=new Thread(()->{
thread1();
});
t1.start();
Thread.sleep(1000);
flag=false;
// The program can stop normally
}
No matter at any time , When one thread entering the synchronized block, will the value of the variable flag be loaded from main memory?
Thank you for your detailed explanation, because I am not sure if the flag has a happend-befores relationship. Literally, the flag is not in the synchronized block.
Update1:
I know that using volatile can and I also know how to write the right code,, but I want to know now if there is no volatile keyword. Whether synchronized can guarantee visibility. Note: the flag variable is not in synchronized block.
Update2:
I updated the code again, the code on my win10+JDK8 system can stop normally, do you think it is correct or accidental, because it is not tested on all hardware systems, so I need theory to guide。
Focus on the question:
whether the loop condition (flag variable) has a happen-before relationship with the synchroized block inside the loop,If it has a happen-before relationship, jvm whether ensure that the flag variable is loaded from main memory even if the flag variable is not in the synchronized block.
If every one think there is no happen-before relationship, then how do you explain that when I remove the synchronized block, the code will loop indefinitely. When I add it, it will stop normally. Is this just an accident?
OK looking a little more closely at your code, what you have is not enough. The access to a shared field is outside of your synchronized block, so no it does not work.
In addition, Java requires that both the read and the write of shared memory be "synchronized" somehow. Using the synchronized keyworld, that usually means you need to use it on both the read and the write, and you did not show the write.
And in addition to that, the "lock" that you use for a given set of fields or shared memory must be the same lock for both the read and the write. Seriously, volatile is a lot easier here, and the API in java.util.concurrent is even easier and recommended. Don't try reinventing the wheel.
private static boolean flag = true; // must use 'resetFlag'
public void resetFlag() { synchronized( "lock" ) {flag = false;} }
public boolean getFlag() { synchronized( "lock" ) {return flag;} }
public void thread1() {
while ( getFlag() ){
synchronized ("lock"){
// other work
}
}
}
public static void main(String[] args) throws Exception {
Thread t1=new Thread(()->{
thread1();
});
t1.start();
Thread.sleep(1000);
resetFlag();
// The program can stop normally
}
I think the above has the required changes.
Regarding your second update: the code on my win10+JDK8 system can stop normally Yes it can. Memory visibility is not guaranteed, but it is not prohibited. Memory can be made visible for any reason, even just "accidentally." On Intel platforms, Intel has a QPI bus which exchanges memory update information at high speed, bypassing the memory bus. However even that can be got around by software, so it's best to just put the synchronization where needed (Hint: look at AtomicBoolean.)
Thanks to the information provided by #xTrollxDudex and #markspace ,The code in the loop section is observed from the jvm level, If there is no
happens-before relationship and the code may be optimized from :
while (flag){
synchronized (lock){
// some work
}
}
to :
if(flag){
while (true){
synchronized (lock){
//some work
}
}
}
To ensure thread visibility, we need to avoid this optimization, such as through the volatile keyword or other synchronization strategies.
The appearance of the sync block in the loop is similar to the function of the enhanced volatile keyword, which guarantees the visibility of the variable in front of it, so when we loop into the sync block for the second time, we can see it latest. The change, which is why the loop can stop normally. It looks fine, but it's not the right synchronization method, so don't do it.
For a detailed explanation, please see a similar question in here
let's say I use a jar that IBM has created.
Let's say that this Jar has a function that I need but is ultimately build as such:
while (true) {
System.out.println(1)
}
(of course it doesn't really just printing 1, but for the example let's say it is)
So, I made the call to the function that does it in another thread using future. How can I completely kill the thread that this code is running in? Or alternatively, how can I kill the asynchronous task in Kotlin that runs the code.
Solutions in Kotlin or Java will be great,
thanks in advance!
EDIT:
I've found out, that if this is a thread, I can Thread#stop() it to really make it stop. But unfortunately making the constructor throwing exceptions multiple times, causes the JVM to erase the class from memory causing a NoClassDefFoundError when instantiating the class the next time..
If you can capture it's thread you should be able to kill it so long as it is doing some kind of blocking function internally.
class OtherFunction implements Runnable {
#Override
public void run() {
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// We assume the thread will exit when interrupted.
System.out.println("Bye!!");
return;
}
System.out.println("Hello");
}
}
}
class Killable implements Runnable {
final Runnable target;
private Thread itsThread;
Killable(Runnable target) {
this.target = target;
}
#Override
public void run() {
// Catch the thread id of the target.
itsThread = Thread.currentThread();
// Launch it.
target.run();
}
public void kill() {
// Give it a good kick.
itsThread.interrupt();
}
}
public void test() throws InterruptedException {
OtherFunction theFunction = new OtherFunction();
Killable killableVersion = new Killable(theFunction);
new Thread(killableVersion).start();
// Wait for a few seconds.
Thread.sleep(10000);
// Kill it.
killableVersion.kill();
}
It seems like Thread#stop() solved my problem. I know it's deprecated and can be prevented with catch(Throwable t) but at least it did the trick for me.
By the way, to get the thread from the executor, I've used AtomicReference<Thread> and set it in the callback.
Thread#stop() is deprecated as 'inherently unsafe' and should be avoided if at all possible.
It's a source of instability and corruption and may fail anyway!
It actually causes a ThreadDeath exception to be throw in the target thread.
The authors of whatever code it pops into are unlikely to have expected that outcome.
Objects may be in an inconsistent state, external resources may be held and get leaked, files may be incompletely written.
There are ways of handling unexpected errors but in practice most code is written assuming it knows which exceptions might be thrown and not in anticipation for such a 'surprise'.
Given ThreadDeath is a Throwable any catch(Throwable t) will catch it and again, unless great care was taken in every piece of code the thread might execute (unrealistic) ThreadDeath might just get absorbed and not end the thread.
The correct way to handle this is declare an atomic variable (usually as part of the Runnable that represents the task.
AtomicBoolean stopThread=new AtomicBoolean(false);
Then write the loop as:
while (!stopThread.get()) {
System.out.println(1);
}
And provide a method:
public void stopThread(){
stopThread.set(true);
}
Alternatively you can use interrupt() and check interrupted(). These are cleaner methods provided in the Thread class. interrupted() has the behaviour of clearing the flag when called. That's not always helpful and while the flag can be examined by Thread.currentThread().isInterrupted() the 'checking the flag clears it' behaviour can be unhelpful and also suffers some of the issues of stop() because it can cause "surprising" exceptions to be throw at points other code has never anticipated. The right approach is to use your own flag and be in full control of where the process decides to quit.
Take your pick.
See also: Java Thread Primitive Deprecation
Ever wondered why when you click 'Cancel' on some concurrent process you are often made to wait ages for it to respond?
This is why. The task needs to come to a well defined point and do any necessary clean up to terminate in a well defined way.
Think of Thread#stop() as like stopping a cyclist by kicking them off their bike. The method here waves a red flag at them and they then come to a halt as swiftly as they safely can.
Thread#stop() should never have been in Java and you should never use it.
You get away with it in development and small systems. It causes havoc in large production environments.
It's not just deprecated as 'not recommended' it is 'inherently unsafe' do not use it.
It's been deprecated for years and its disappointing that some 'removal date' has never been advertised.
Here's an example that uses either Thread#stop() or interrupt() depending on whether you opt for being dangerous.
import java.lang.System;
import java.lang.Thread;
class Ideone
{
private static boolean beDangerous=true;//Indicates if we're going to use the Thread#stop()....
//This main method uses either stop() or interrupt() depending on the option.
public static void main (String[] args) throws java.lang.Exception
{
PrimeFactor factor=new PrimeFactor();
try{
for(int i=1;i<30;++i){
Thread thrd=new Thread(new Primer(factor));
thrd.start();
Thread.sleep(10);//Represents some concurrent processing...
if(beDangerous){
thrd.stop();
}else{
thrd.interrupt();
}
thrd.join();
if(!factor.check()){
System.out.println("Oops at "+i);
}
}
}catch(Throwable t){
System.out.println(t);
}
}
//This class just hammers the PrimeFactor object until interrupt()ed (or stop()ed).
private static class Primer implements Runnable {
private PrimeFactor factor;
public Primer(PrimeFactor ifactor){
factor=ifactor;
}
public void run(){
int i=1;
while(!Thread.interrupted()){
factor.set(i++);
}
}
}
//Don't worry about this bit too much.
//It's a class that does a non-trivial calculation and that's all we need to know.
//"You're not expected to understand this". If you don't get the joke, Google it.
//This class calculates the largest prime factor of some given number.
//Here it represents a class that ensures internal consistency using synchronized.
//But if we use Thread#stop() this apprently thread-safe class will be broken.
private static class PrimeFactor {
private long num;
private long prime;
public static long getFactor(long num){
if(num<=1){
return num;
}
long temp=num;
long factor=2;
for(int i=2;temp!=1;++i){
if(temp%i==0){
factor=i;
do{
temp=temp/i;
}while(temp%i==0);
}
}
return factor;
}
public synchronized void set(long value){
num=value;
prime=getFactor(value);
}
public synchronized boolean check(){
return prime==getFactor(num);
}
}
}
Typical partial output:
Oops at 1
Oops at 2
Oops at 3
Oops at 6
Oops at 8
Notice that the PrimeFactor class can be described as thread-safe. All it's methods are synchronized. Imagine it's in some library. It's unrealistic to expect "thread-safe" to mean Thread#stop()-safe and the only way to do that would be intrusive. Putting calls to it in a try-catch(ThreadDeath tde) block won't fix anything. The damage will have been down before it's caught.
Don't convince yourself that changing set() to the following solves it:
public synchronized void set(long value){
long temp=getFactor(value);
num=value;
prime=temp;
}
First and foremost the the ThreadDeath exception could throw during the assignments so all that does is potentially shorten the odds on the Race Condition. It hasn't been negated. Never make "how likely is that to happen" arguments about race conditions. Programs call methods billions of times so billion to one-shots come up regularly.
To use Thread#stop() you can essentially never use any library objects including java.* and jump through hoops to handle ThreadDeath everywhere in your code and almost certainly eventually fail anyway.
In java there is no official way of killing thread. This is bug. (no need to argue with it here) Thread#stop() should not be deprecated. It may be improved that it cannot be consumed. Even now it will work most of the time just fine.
Right now, if I write function which will be executed with kill need, I would start new thread and joint to it with timeout or other disconnect mechanism. This will make your code to continue like main thread was killed. Problem is that main thread is still running. All resources are still in use. This is still better than application being frozen. Calling thread.interrupt() is first step but it this does not work using thread.stop() is adequate here. It won't make things worse.
If you really must kill the thread, only way would be to start another jvm via jni, run unsafe code there and use linux kill -9 to stop the whole process if needed.
I believe killing thread is perfectly possible, only jvm developers didn't care enough. I get into this situation all the time and answers like don't use any libraries, fix all foreign code, write your own language or live with it are just frustrating.
I have two methods, foo() and bar(). There will be multiple threads calling these methods, possibly at the same time. It is potentially troublesome if foo() and bar() are run concurrently, as the interleaving of their internal logic can leave the system in an an inconsistent state. However, it it is perfectly ok, and in fact desirable, for multiple threads to be able to call foo() at the same time, and for multiple threads to be able to call bar() at the same time. The final condition is that foo() is expected to return asap, whereas there is no hard time constraint on bar().
I have been considering various ways in which it might be best to control this behaviour. Using synchronized in its simplest form doesn't work because this will block concurrent calls to each method. At first I thought ReadWriteLock might be a good fit, but this would only allow one of the methods to be called concurrently with itself. Another possibility I considered was queuing up requests for these methods on two separate queues and having a consumer which will concurrently execute every foo() in the queue, and then every bar() in the queue, but this seems like it would be difficult to tune so as to avoid unnecessary blocking of foo().
Any suggestions?
I think a good solution would be to make a separate class that controlled access to each of the methods. You would create a singleton of this class, and then use it to control when it is OK to proceed with entering either method.
This is the third iteration. This one prevents starvation.
Usage could be external to the foo() call:
em.enterFoo(Thread.currentThread());
foo();
em.exitFoo();
but would probably be cleaner as calls at the entry and exit of foo() instead, if possible.
Code:
public static class EntryManager
{
private int inFoo = 0;
private int inBar = 0;
private Queue<Thread> queue = new LinkedList<>();
public synchronized void enterBar(Thread t) throws InterruptedException
{
// Place the Thread on the queue
queue.add(t);
while(queue.peek() != t)
{
// Wait until the passed Thread is at the head of the queue.
this.wait();
}
while(inFoo > 0)
{
// Wait until there is no one in foo().
this.wait();
}
// There is no one in foo. So this thread can enter bar.
// Remove the thread from the queue.
queue.remove();
inBar++;
// Wakeup everyone.
this.notifyAll();
}
public synchronized void enterFoo(Thread t) throws InterruptedException
{
// Place the thread on the queue
queue.add(t);
while(queue.peek() != t)
{
// Wait until the passed Thread is at the head of the queue.
this.wait();
}
while(inBar > 0)
{
this.wait();
}
// There is no one in bar. So this thread can enter foo.
// Remove the thread from the queue.
queue.remove();
inFoo++;
// Wakeup everyone.
this.notifyAll();
}
public synchronized void exitBar()
{
inBar--;
// Wakeup everyone.
this.notifyAll();
}
public synchronized void exitFoo()
{
inFoo--;
// Wakeup everyone.
this.notifyAll();
}
}
I don't know of a name for that problem, so I would write my own synchronization helper object to deal with it. It sounds a lot like a reader/writer lock, except that where a reader/writer lock allows any number of readers at the same time, or exactly one writer, but not both; your lock would allow any number of foo() or any number of bar(), but not both.
The tricky part is going to be ensuring that the lock is fair. No problem if there's no contention, but what if the lock is in "foo" mode, and there's a steady stream of threads that want to call foo(), and just one or two that want to call bar(). How do the bar() threads ever get to run?
Actually, it reminds me a lot of a traffic light at a busy highway intersection. The traffic light can allow cars to flow on the east/west route, or on the north/south route, but not both. You don't want the light to switch too often and just let one or two cars through per cycle because that would be inefficient. But you also don't want the light to make drivers wait so long that they get angry.
I've got a feeling that the policy may have to be custom-tailored for your particular application. I.e., it may depend on how often the two functions are called, whether they are called in bursts, etc.
I would start from the source code of a reader/writer lock, and try to hack it up until it worked for me.
I got a question about interrupting threads in Java. Say I have a Runnable:
public MyRunnable implements Runnable {
public void run() {
operationOne();
operationTwo();
operationThree();
}
}
I want to implement something like this:
Thread t = new Thread(new MyRunnable());
t.run();
... // something happens
// we now want to stop Thread t
t.interrupt(); // MyRunnable receives an InterruptedException, right?
... // t is has now been terminated.
How can I implement this in Java? Specifically, how do I catch the InterruptedException in MyRunnable?
I recommend testing for Thread.isInterrupted(). Javadoc here. The idea here is that you are doing some work, most likely in a loop. On every iteration you should check if the interrupted flag is true and stop the work.
while(doingWork && !Thread.isInterrupted() {
// do the work
}
Edit: To be clear, your thread won't receive an InterruptedException if the sub tasks are not blocking or worst, eat that exception. Checking for the flag is the right method but not everybody follows it.
First, the 2nd line of your 2nd block of code should be t.start(), not t.run(). t.run() simply calls your run method in-line.
And yes, MyRunnable.run() must check periodically, while it is running, for Thread.currentThread().isInterrupted(). Since many things you might want to do in a Runnable involve InterruptedExceptions, my advice is to bite the bullet and live with them. Periodically call a utility function
public static void checkForInterrupt() throws InterruptedException {
if (Thread.currentThread().isInterrupted())
throw new InterruptedException();
}
EDIT added
Since I see a comment that the poster has no control over the individual operations, his MyRunnable.run() code should look like
public void run() {
operation1();
checkForInterrupt();
operation2();
checkForInterrupt();
operation3();
}
an InterruptedThreadException is only thrown when the thread is being blocked (wait, sleep, etc.) . Otherwise, you'll have to check Thread.currentThread().isInterrupted().
I think the answers above will pretty much fit your problem. I just want to add something on InterruptedException
Javadoc says:
InterruptedException :Thrown when a thread is waiting, sleeping, or
otherwise paused for a long time and another thread interrupts it
using the interrupt method in class Thread.
This means InterruptedException won't be thrown while running
operationOne();
operationTwo();
operationThree();
unless you are either sleeping, waiting for a lock or paused somewhere in these three methods.
EDIT If the provided code can not be changed as suggested by the nice and useful answers around here then I am afraid you have no way of interrupting your thread. As apposed to other languages such as C# where a thread can be aborted by calling Thread.Abort() Java does not have that possibility. See this link to know more about the exact reasons.
First of all, should be class in there
public class MyRunnable extends Thread {
public void run() {
if(!isInterrupted()){
operationOne();
operationTwo();
operationThree();
}
}
}
Would this work better?