BLOCKED versus WAITING

BLOCKED and WAITING, as a result, are threads suspended and do not consume CPU resources, although there are some differences

BLOCKED

The thread state of a blocked thread waiting for a Monitor lock to enter a synchronized Block or Method, or re-enter a synchronized Block/Method after calling Object.wait. Simply put, it is the state of a thread waiting for a synchronized lock

In the following code, T1 is BLOCKED while waiting for T0’s lock release (synchronized block execution is complete)

Object lock = new Object();
Thread t0 = new Thread(new Runnable() {
    @Override
    public void run(a) {
        synchronized (lock){
            System.out.println("t0 acquire lock success");
            try {
                Thread.sleep(10000);
            } catch(InterruptedException e) { e.printStackTrace(); }}}}); t0.start(); Thread.sleep(100);
Thread t1 = new Thread(new Runnable() {
    @Override
    public void run(a) {
        synchronized (lock){
            System.out.println("t1 acquire lock success"); }}}); t1.start(); Thread.sleep(100);
System.out.println("t0 state: "+t0.getState());
System.out.println("t1 state: "+t1.getState());
System.out.println("done.");

//output
t0 acquire lock success
t0 state: TIMED_WAITING
t1 state: BLOCKED
done.
t1 acquire lock success
Copy the code

WAITING

WAITING state. The following methods cause the thread to be in WAITING state:

  • Object.wait()
  • Thread.join()
  • LockSupport.park()

A thread in a WAITING state is WAITING for another thread to perform some operation. For example, a thread that called Object.wait() on an Object is WAITING for another thread to call Object.notify() or Object.notifyAll() on that Object. The Thread for thread.join () is waiting for the specified Thread to stop.

In the following code, T0 acquires the lock through synchronized and waits, causing T0 to enter the WAITING state:

Object lock = new Object();
Thread t0 = new Thread(new Runnable() {
    @Override
    public void run(a) {
        synchronized (lock){
            System.out.println("t0 acquire lock success");
            try {
                lock.wait();
            } catch(InterruptedException e) { e.printStackTrace(); }}}}); t0.start(); Thread.sleep(100);
System.out.println("t0 state: "+t0.getState());
System.out.println("done.");

//output
t0 acquire lock success
t0 state: WAITING
done.
Copy the code

The difference between

In addition to synchronized Block/Method locking, JAVA also provides a lock implementation under JUC, which is more powerful under juc.lock. Such as support interrupt, support reentrant/non-reentrant, fair/non-fair; But juC locks are not quite the same as synchronized implementations

Synchronized waiting for a lock: synchronized waiting for a lock

ReentrantLock reentrantLock = new ReentrantLock();
Thread t0 = new Thread(new Runnable() {
    @Override
    public void run(a) {
        reentrantLock.lock();

        System.out.println("t0 acquire lock success");
        try {
            Thread.sleep(10000);
        } catch(InterruptedException e) { e.printStackTrace(); }}}); t0.start(); Thread.sleep(100);
Thread t1 = new Thread(new Runnable() {
    @Override
    public void run(a) {
        reentrantLock.lock();
        System.out.println("t1 acquire lock success"); }}); t1.start(); Thread.sleep(100);
System.out.println("t0 state: "+t0.getState());
System.out.println("t1 state: "+t1.getState());
System.out.println("done.");

//output
t0 acquire lock success
t0 state: TIMED_WAITING
t1 state: WAITING
done.
Copy the code

When the thread status is observed, the BLOCKED state is not only locked, but also WAITING/TIMEWAITING state may still be the state WAITING for the lock

Jstack has a note for WAITING in the form of PARKING, so it can be seen when the thread is in the stack:

// The wait type is shown here"Thread-0" #11 prio=5 os_prio=31 tid=0x00007f9308110000 nid=0x5c03 waiting on condition [0x0000700007fc3000]Java.lang.Thread.State: WAITING (parking)// At sun.misc.Unsafe. Park (Native Method)Copy the code

Synchronized locks have a different output in jStack:

// The wait type is monitor"Thread-1" #12 prio=5 os_prio=31 tid=0x00007f833d919800 nid=0x5a03 waiting for monitor entry [0x00007000035af000]Java.lang.thread. State: BLOCKED (on object monitor)// The State is BLOCKED, which indicates the ownership of the monitorCopy the code

Note the difference between object.wait () and juC lock WAITING when observing thread state

Is RUNNABLE really RUNNABLE?

Here is an example of jStack output. The thread is now executing the socketRead0 method (Native) and is in a RUNNABLE state

"RMI TCP Connection(2)-192.xxx.xx.xx" daemon prio=6 tid=0x000000000a3e8800 nid=0x158e50 runnable [0x000000000adbe000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.io.BufferedInputStream.fill(Unknown Source)
at java.io.BufferedInputStream.read(Unknown Source)
- locked (0x00000007ad784010) (a java.io.BufferedInputStream)
at java.io.FilterInputStream.read(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Copy the code

RUNNABLE is a JAVA thread state. The thread is WAITING. SocketInputStream is a BIO implementation that blocks when no data is received (or ready to read). The block is RUNNABLE in the JAVA thread state, but does not consume CPU time chips in the user state. The kernel terminates the block when it receives data

reference

  • Blog. Fastthread. IO / 2018/09/02 /…