Y said

I have nothing to say today. I personally love taking pictures of the sky, so let me show you a picture I took a while ago at night.

Does the join method release the lock?

If the wait method is used to release the lock, the wait method will release the lock. If the wait method is used to release the lock, the wait method will release the lock.

Release the Thread object lock

Let’s start with an example from the book:

public class Join {
    static class ThreadA implements Runnable {

        @Override
        public void run(a) {
            try {
                System.out.println("I'm a child thread. I'll sleep for a second.");
                Thread.sleep(1000);
                System.out.println("I'm a child thread. I'm done for a second.");
            } catch(InterruptedException e) { e.printStackTrace(); }}}public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new ThreadA());
        thread.start();
        thread.join();
        System.out.println("If I don't add the join method, I will be typed out first. If I add the join method, it will be different."); }}Copy the code

In this example, we called Thread.join () in the main method, which prints:

I'm a child thread, I'm going to sleep for a second. I'm a child thread, I'm going to sleep for a second. If I don't add join, I'm going to get knocked out firstCopy the code

The purpose of this example is simple: the main thread waits for the thread to complete its execution and then continues its execution through the join method of the Thread instance.

How does the join method implement this functionality underneath? Will it release the lock at all? Let’s click on the source code.

if (millis == 0) {
    while (isAlive()) {
        wait(0); }}else {
    while (isAlive()) {
        long delay = millis - now;
        if (delay <= 0) {
            break; } wait(delay); now = System.currentTimeMillis() - base; }}Copy the code

As you can see, underneath the join is the wait(long) method called. The wait method is an instance of the Object type. It releases the lock of the current Object and requires the lock of the current Object.

That might be a little tricky to say. As we all know, Java locks are essentially object locks. Since we called Thread.join (), the “lock” object here is actually thread. Wait releases the thread lock.

If the main method is used to hold the object lock thread, it will be used to hold the object lock thread.

public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(new ThreadA());
    thread.start();
    new Thread(() -> {
        // Hold thread objects as locks, so that the wait in the following join cannot be executed until the lock is released.
        synchronized (thread) {
            try {
                System.out.println("I'm holding thread lock.");
                Thread.sleep(10000);
                System.out.println("I've released the thread lock.");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }).start();
    thread.join();
    System.out.println("If I don't add the join method, I will be typed out first. If I add the join method, it will be different.");
}
Copy the code

Print result:

I'm a child thread and I'm going to sleep for a second and I'm going to sleep for a second and I'm going to sleep for a second and I'm going to release the thread lock and if I don't add join, I'm going to get knocked out firstCopy the code

This confirms the statement that the lock of the current object is required before the wait method can be executed.

So back to the original question: Does the join() method release the lock? Yan jin’s answer is that it releases the object lock on thread instances, but not on other objects (including the main thread). Does thread.join () release the lock? Or continue to hold it? .

In short, you are also right to say that it released the lock because it did release the thread object lock through the wait method, and you are also right to say that it did not release the lock because, from the perspective of the calling thread, it did not release the object lock held by the current calling thread.

Of course, to prevent other readers from seeing this and wondering, I simply deleted that sentence from the article.

Who woke up?

See this, I have a new question: join method inside a while loop. Wait releases the lock, and someone must wake it up before the program can proceed. There must be a place where the notify method of thread objects is called.

We can find an exit() method in the Thread class with a note that says: This method is called by the system to give a Thread a chance to clean up before it actually exits.

So simple English we should be able to understand it?

It contains this code:

if(group ! =null) {
    group.threadTerminated(this);
    group = null;
}

void threadTerminated(Thread t) {
    synchronized (this) {
        remove(t);

        if (nthreads == 0) {
            notifyAll();
        }
        if (daemon && (nthreads == 0) &&
            (nUnstartedThreads == 0) && (ngroups == 0)) { destroy(); }}}Copy the code

At first I thought it was called here, but on closer inspection, the object called here is an instance of ThreadGroup, not thread. So it’s probably not the right place.

After some googling, I found the correct answer on StackOverflow (yyds) : who and when notify the thread.wait() when thread.join() is called?

The answer is that this is done at the JVM level:

static void ensure_join(JavaThread* thread) {
  // We do not need to grap the Threads_lock, since we are operating on ourself.
  Handle threadObj(thread, thread->threadObj());
  assert(threadObj.not_null(), "java thread object must exist");
  ObjectLocker lock(threadObj, thread);
  // Ignore pending exception (ThreadDeath), since we are exiting anyway
  thread->clear_pending_exception(a);// Thread is exiting. So set thread_status field in java.lang.Thread class to TERMINATED.
  java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);
  // Clear the native thread instance - this makes isAlive return false and allows the join()
  // to complete once we've done the notify_all below
  java_lang_Thread::set_thread(threadObj(), NULL);
  lock.notify_all(thread);
  // Ignore pending exception (ThreadDeath), since we are exiting anyway
  thread->clear_pending_exception(a); }Copy the code

You can see that in addition to notify_all, it actually does a lot of cleaning. This includes handling exceptions and setting thread status.

If the thread is not started

Changing the code again, what happens if the thread is not started by start?

Thread thread = new Thread(new ThreadA());
// thread.start();
thread.join();
System.out.println("If I don't add the join method, I will be typed out first. If I add the join method, it will be different.");
Copy the code

It prints the last line of code directly.

Before a wait, there is an isAlive() check to see if the current thread isAlive. If there is no start, false is returned and wait is not entered.

conclusion

The Join method releases the Thread object lock, followed by the wait method, which notify_all is invoked at the JVM level.

And a support

I’m Yasin, a blogger who insists on technical originality. My WX official account is: Made a Program

All see here, if feel my article write also ok, might as well support once.

The first article will be sent to the public account, the best reading experience, welcome your attention.

Your every retweet, attention, like, comment is the biggest support for me!

There are learning resources, and frontline Internet companies within the push oh

And a support

My name is Yasin, a blogger who insists on original technology. My wechat official account is: Made a Program

All see here, if feel my article write also ok, might as well support once.

The first article will be sent to the public account, the best reading experience, welcome your attention.

Your every retweet, attention, like, comment is the biggest support for me!

There are learning resources, and frontline Internet companies within the push oh