简体   繁体   中英

Why part of HandlerThread's run() method is synchronized?

I'm going thru HandlerThread source code and I can't understand why part of HandlerThread's run() method is synchronized?

@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

I thought that the run() method is called on the thread it belongs to so how can it be reached from multiple threads?

I expect it has sth to do with the situation when somebody create and start multiple instances of the same HandlerThread class.

The reason it is synchronized is that it is required in order to call notifyAll .

See the JavaDoc :

This method should only be called by a thread that is the owner of this object's monitor. A thread becomes the owner of the object's monitor in one of three ways:

  • By executing a synchronized instance method of that object.

  • By executing the body of a synchronized statement that synchronizes on the object.

  • For objects of type Class, by executing a synchronized static method of that class.

Only one thread at a time can own an object's monitor.

The caller of notifyAll() must hold a lock on the object, so that's why that statement is in the synchronized block. The assignment of mLooper is synchronized to ensure that the write is visible to other threads, specifically the caller(s) of HandlerThread#getLooper() , which contains this code:

    // If the thread has been started, wait until the looper has been created.
    synchronized (this) {
        while (isAlive() && mLooper == null) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
    }

The getLooper() method is supposed to return the Looper instance connected to the HandlerThread . Also this getter should be thread-safe for obvious reasons. So the implementation waits indefinitely, while the run() methods notifies all waiting threads after mLooper is setup.

public void run() {
    ...
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    ...
}

public Looper getLooper() {
    ...
    synchronized (this) {
        while (isAlive() && mLooper == null) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
    }
    return mLooper;
}

The synchronized blocks are the minimal parts of the code to require the intrinsic lock which the wait() method suspends.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM