Java线程状态操做和锁与监视器的区别

进入正题前须要了解的概念

  • Java中的线程的状态分为6种。

  1. 初始(NEW):新建立了一个线程对象,但尚未调用start()方法。
  2. 运行(RUNNABLE):Java线程准备就绪(ready)和运行中(running)两种状态笼统的成为“运行”。
    线程对象建立后,其余线程(好比main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权,此时处于就绪状态(ready)。就绪状态的线程在得到cpu 时间片后变为运行中状态(running)。
  3. 阻塞(BLOCKED):表线程阻塞于锁。
  4. 等待(WAITING):进入该状态的线程须要等待其余线程作出一些特定动做(通知或中断)。
  5. 超时等待(TIME_WAITING):该状态不一样于WAITING,它能够在指定的时间内自行返回。
  6. 终止(TERMINATED):表示该线程已经执行完毕。
  •  锁与监视器的区别

  1. JVM为每个对象和类都关联一个锁,锁住了一个对象,就是得到对象相关联的监视器。
  2. 当声明 synchronized 的代码块时,编译而成的字节码会包含一个监视器和多个监视器退出路径 (多个退出路径,正常和异常状况),当执行被锁的代码时,检查目标锁对象的计数器是否为0,若是为0则将锁对象的持有线程设置为本身,而后计数器加1,获取到锁,若是不为0则检查锁对象的持有线程是否是本身,若是是本身就将计数器加1获取锁,若是不是则阻塞等待,退出的时候计数器减1,当减为0的时候清楚锁对象的持有线程标记。(能够看出 synchronized 是支持可重入的)
  3. 逻辑上锁是对象内存堆中头部的一部分数据。JVM中的每一个对象都有一个锁,任何程序均可以使用它来协调对对象的多线程访问。若是任何线程想要访问该对象的实例变量,那么线程必须拥有该对象的锁(在锁内存区域设置的标志)。全部其余的线程试图访问该对象的变量,必须等到拥有该对象的锁有的线程释放锁(改变标记)。
  4. 监视器是任何一个对象都有的内置的同步数据结构,它是用来协调有多个线程调用当前对象的时的执行顺序,线程会block或者wait 在一个对象的监视器上,可理解为监视器确保只有一个线程访问共享资源,所有期待得到锁的线程,在锁已经被其它线程拥有的时候,这些期待得到锁的线程就进入了监视器的entry set区域。全部曾经得到过锁,可是因为其它必要条件不知足而须要wait的时候,线程就进入了监视器的wait set区域 。在wait set区域的线程得到Notify/notifyAll通知的时候,随机的一个Thread(Notify)或者是所有的Thread(NotifyALL)从监视器的wait set区域进入了entry set中。在当前拥有锁的线程释放掉锁的时候,处于该监视器的entryset区域的线程都会抢占该锁,可是只能有任意的一个Thread能取得该锁,而其余线程依然在entry set中等待下次来抢占到锁以后再执行。 

       

  • 因此,监视器实际上就是实现synchronized锁的具体实现方法
  • jdk文档中的描述

  • wait:当前线程必须拥有此对象监视器。该线程发布对此监视器的全部权并等待,直到其余线程经过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。而后该线程将等到从新得到对监视器的全部权后才能继续执行。
  • notify:唤醒在此对象监视器上等待的单个线程。若是全部线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现作出决定时发生。线程经过调用其中一个 wait 方法,在对象的监视器上等待。直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其余全部线程进行竞争;例如,唤醒的线程在做为锁定此对象的下一个线程方面没有可靠的特权或劣势。
  • notifyAll:唤醒在此对象监视器上等待的全部线程。线程经过调用其中一个 wait 方法,在对象的监视器上等待。直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其余全部线程进行竞争;例如,唤醒的线程在做为锁定此对象的下一个线程方面没有可靠的特权或劣势。
package test;

public class Test1 {

    private static Object[] objs = new Object[10];

    public static void main(String[] args) {

        Runnable run1 = new Runnable() {

            @Override
            public void run() {
                synchronized (objs) {
                    try {
                        System.out.println(1);
                        objs.wait();
                        System.out.println(2);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }
        };

        Runnable run2 = new Runnable() {

            @Override
            public void run() {
                synchronized (objs) {
                    System.out.println(3);
                    objs.notify();
                }
            }
        };

        new Thread(run1).start();
        new Thread(run2).start();
    }

}


运行结果
1
3
2
相关文章
相关标签/搜索