同步监视器

监视器可以看作是包含一个特殊房间的建筑物。这个特殊的房间一次只能容纳一个客户(线程)。这个房间通常包含一些数据和代码。如果客户想要占用这个特殊的房间,他必须先进入走廊(入口)等待。调度程序将选择一个基于一些标准(例如。先进先出)。如果他因为某种原因被停职,他将被送到等候室,并安排稍后重新进入特别室。简单地说,监视器是监视线程对特定房间的访问的工具。它确保只有一个线程可以访问受保护的数据或代码。

同步块

public void run() {
        try {
            while (true) {
                /**
                 * 同步块监视对象
                 */
                synchronized (p) {
                    //在圆括号里,一定要加一个大家能访问到的同一个对象。
                    //synchronized为同步监视器(java),
                    //互斥对象(C)。括号为同步块(临界区)。
                    if (this.p.pack <= 0) {
                        break;
                    }
                    System.out.println( this.name + "吃第" + this.p.pack + "个包子" );
                    this.p.pack--;
              }

                Thread.sleep( 10 );
             }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

同步方法

public class 包子笼 {
    public int pack = 100;

    /**
     * 同步方法监视对象
     */

    //依赖
    public synchronized void eat(String name) {
        //这里同步监视器的对象是this(即包子笼)
        System.out.println( name + "吃第" + this.pack + "个包子" );
        this.pack--;
    }
}
public void run() {
        try {
            while (true) {
                if (this.p.pack <= 0) {
                    break;
                }
                //这里会出现吃到第0个包子,
                //对与第一个线程,他在判断包子已经吃完,
                //但是,在p--之前,执行时间用完了。
                //该项成就就休眠了了。由于另外一个线程继续从头执行,
                //所以跳过了之前的p==0的判断,而且p--已执行。
                //就直接输出当时p--后的结果了。
                p.eat( this.name );
                 Thread.sleep( 10 );
                }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

 

一个线程执行到synchronized代码时,会在加锁的对象上,关联一个同步监视器

 

java 实时监控屏幕 java监视器_加锁

蓝色空矩形为同步监视器,红色为对象

java 实时监控屏幕 java监视器_System_02

红色为同步监视器

线程进入同步区等于获得对象的锁,如果一个线程进入同步区,其他线程不能进入,直到当前线程离开同步代(synchronized)释放锁,其他对象才能进入一个线程也可能执行wait()进入等待区,释放锁,其他线程执行进入同步区并向等待区的线程发通知
等待区可以有多个线程在等待,同步区线程发通知应该全部发,入口和等待区的线程都应该受到通知。有监视器才有等待区
等待和通知方法必须通过加锁对象调用。

作者:ssttIsme