LockSupport is a very handy thread blocking tool. It can block a thread anywhere in the thread.

Compared to the Thread.suspend() method, it makes up for cases where a Thread cannot continue because of the resume() method.

Unlike the object.wait () method, it does not require an Object lock first and does not throw InterruptedException

LockSupport’s static method park() blocks the current thread, as do parkNanos(), parkUntil(), and so on. They implement a timed wait.

Support for periodic blocking

A wrong example

package com.shockang.study.java.concurrent.thread.suspend;

public class SuspendDemo {
	public static Object u = new Object();
	static ChangeObjectThread t1 = new ChangeObjectThread("t1");
	static ChangeObjectThread t2 = new ChangeObjectThread("t2");

	public static class ChangeObjectThread extends Thread {
		public ChangeObjectThread(String name){
			super.setName(name);
		}
		@Override
		public void run(a) {
			synchronized (u) {
				System.out.println("in "+getName()); Thread.currentThread().suspend(); }}}public static void main(String[] args) throws InterruptedException {
		t1.start();
		Thread.sleep(100); t2.start(); t1.resume(); t2.resume(); t1.join(); t2.join(); }}Copy the code

The result of the above program is:On the current system, thread 2 is actually suspended, but it does have a RUNNABLE thread state, which can misjudge the current system state. Meanwhile, resume() is already called in the main function, but because of the chronological order, that resume is not in effect! This results in thread 2 being permanently suspended and holding the lock on object U forever. This could be fatal to the system.

How to improve?

package com.shockang.study.java.concurrent.lock;

import java.util.concurrent.locks.LockSupport;

public class LockSupportDemo {
    private static Object u = new Object();
    static ChangeObjectThread t1 = new ChangeObjectThread("t1");
    static ChangeObjectThread t2 = new ChangeObjectThread("t2");

    public static class ChangeObjectThread extends Thread {
        public ChangeObjectThread(String name) {
            super.setName(name);
        }

        @Override
        public void run(a) {
            synchronized (u) {
                System.out.println("in "+ getName()); LockSupport.park(); }}}public static void main(String[] args) throws InterruptedException {
        t1.start();
        Thread.sleep(100); t2.start(); LockSupport.unpark(t1); LockSupport.unpark(t2); t1.join(); t2.join(); }}Copy the code

Note that the suspend and resume methods are simply replaced with the park() and unpack() methods.

There is no guarantee that the unpack() method occurs after the Park () method.

But by executing this code, you can see that it closes normally throughout, without the thread hanging for long periods because of the park() method.

This is because the LockSupport class uses a semaphore like mechanism.

It have a license for each thread, if the license is available, then the park () method will return immediately, and consumption of this license (i.e. permission will become unavailable), if the license is not available, will be blocked and unpark () method is a license becomes available, but unlike the semaphore, cannot accumulate, You can’t have more than one license, it’s always one).

This feature allows the next park() method operation to return immediately, even if the unpark() method operation occurs before the park() method.

Support interruption impact

In addition to timing blocking, the locksupport.park () method also supports interrupt effects.

But unlike other functions that receive interrupts, the locksupport.park () method does not throw InterruptedException.

It only returns silently, but we can get the interrupt flag from methods like Thread.interrupted().

package com.shockang.study.java.concurrent.lock;

import java.util.concurrent.locks.LockSupport;

public class LockSupportIntDemo {
    private static Object u = new Object();
    static ChangeObjectThread t1 = new ChangeObjectThread("t1");
    static ChangeObjectThread t2 = new ChangeObjectThread("t2");

    public static class ChangeObjectThread extends Thread {
        public ChangeObjectThread(String name) {
            super.setName(name);
        }

        @Override
        public void run(a) {
            synchronized (u) {
                System.out.println("in " + getName());
                LockSupport.park();
                if (Thread.interrupted()) {
                    System.out.println(getName() + "Interrupted.");
                }
            }
            System.out.println(getName() + "End of execution"); }}public static void main(String[] args) throws InterruptedException {
        t1.start();
        Thread.sleep(100); t2.start(); t1.interrupt(); LockSupport.unpark(t2); }}Copy the code