同步监视器
监视器可以看作是包含一个特殊房间的建筑物。这个特殊的房间一次只能容纳一个客户(线程)。这个房间通常包含一些数据和代码。如果客户想要占用这个特殊的房间,他必须先进入走廊(入口)等待。调度程序将选择一个基于一些标准(例如。先进先出)。如果他因为某种原因被停职,他将被送到等候室,并安排稍后重新进入特别室。简单地说,监视器是监视线程对特定房间的访问的工具。它确保只有一个线程可以访问受保护的数据或代码。
同步块
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代码时,会在加锁的对象上,关联一个同步监视器
蓝色空矩形为同步监视器,红色为对象
红色为同步监视器
线程进入同步区等于获得对象的锁,如果一个线程进入同步区,其他线程不能进入,直到当前线程离开同步代(synchronized)释放锁,其他对象才能进入一个线程也可能执行wait()进入等待区,释放锁,其他线程执行进入同步区并向等待区的线程发通知
等待区可以有多个线程在等待,同步区线程发通知应该全部发,入口和等待区的线程都应该受到通知。有监视器才有等待区
等待和通知方法必须通过加锁对象调用。作者:ssttIsme