乐趣区

关于多线程:3线程一共有哪些状态呢二

在上一章中介绍了使线程进入 timed_waiting 状态的 3 种办法

1. Thread.sleep(long)
2. Object.wait(long)
3. Thread.join(long)

接下来持续 实战 使线程进入 BLOCKED 状态的办法

synchronized 会使线程进入 BLOCKED 状态


/**
 * synchronized 线程处于 timed_waiting 状态
 *
 * @author jinglei
 * @date 2020/8/21 13:09
 */
public class TimedWaitingBySync {private static Object lock = new Object();

    public static void main(String[] args) {Thread syncLongThread = new Thread(new Runnable() {
            @Override
            public void run() {synchronized (lock){System.out.println("子线程无奈进入同步代码块");
                }

            }
        });
        syncLongThread.setName("mythread-sync");

        // 启动线程
        syncLongThread.start();
        // 留神,这个中央并不一定会保障主线程优先于子线程执行,具体哪个线程先执行是由 CPU 依据过后的系统资源调度的,
        // 只管大部分状况可能看到是主线程优先执行
        synchronized (lock){while(true){}}
    }

}

依照如下步骤查看线程堆栈

堆栈内容如下

能够看出线程进入了 BLOCKED 状态,并且是在一个对象锁或者是对象监视器上阻塞,当前看到这种日志就是阐明此线程须要获取一个对象锁,然而这个锁曾经被其余线程占有了,该线程只能进入阻塞队列期待其余线程开释锁。

谈到 synchronized 就不得不说下经典的死锁问题,死锁指的是两个及其以上线程在别离持有了相应的锁的同时,还须要对方曾经持有的锁,并且本身曾经持有的锁不会被动去开释,此时就造成了一个死循环,也就是死锁。

现实生活中的例子,比方有一双筷子,李梅和韩雷雷别离领有了一根筷子,他们都不会把本人的筷子给他人还想要对方的筷子,这就形成了死锁。

废话不持续了,上代码


/**
 * sync 导致的死锁
 *
 * @author jinglei
 * @date 2020/8/24 16:22
 */
public class SyncDeadLock {private static Object tLock = new Object();
    private static Object sLock = new Object();

    static class Teacher implements Runnable{

        @Override
        public void run() {synchronized (tLock){System.out.println("老师持有了 tLock 锁,还须要获取 sLock 锁");
                try {
                    // 休眠 1 秒为了让 Student 有工夫去获取 sLock 锁
                    Thread.sleep(1000);
                } catch (InterruptedException e) {e.printStackTrace();
                }
                synchronized (sLock){System.out.println("老师更新问题");
                }
            }
        }
    }

    static class Student implements Runnable {
        @Override
        public void run() {synchronized (sLock){System.out.println("学生持有了 sLock 锁,还须要获取 tLock 锁");
                synchronized (tLock){System.out.println("学生更新问题");
                }
            }
        }
    }

    public static void main(String[] args) {new Thread(new Teacher()).start();
        new Thread(new Student()).start();}
}

咱们创立了两个线程 Teacher 和 Student,这两个线程执行 run 办法须要获取两把锁
Teacher 先获取 tLock,再去获取 sLock
Student 先获取 sLock,再去获取 tLock
在 Teacher 的 run 办法中有句 Thread.sleep(1000); 是为了让 Teacher 让出 cpu 以保障 Student 获取 sLock 锁,从而造成死锁条件。

程序运行后,获取堆栈信息

堆栈如下图

能够看出 Thread- 1 也就是 Student 线程曾经获取了锁 0x000000076bee60c8,在期待 0x000000076bee60b8
Thread- 0 也就是 Teacher 获取了 0x000000076bee60b8,在期待 0x000000076bee60c8。
从而造成了死锁场面

退出移动版