我理解你的意思。你的理解大部分都没有问题。出现误解的关键在于,对“同步”这一关键词,所表述的主体理解错误了。这也是很多人都理解错的,或者没有理解到位的地方。synchronized 同步化的,其实指的不是线程,而是加了这个关键词的某个方法,或者代码块。看实际的用法其实就知道了
public synchronized void method(){}
这个方法加了 synchronized 关键字之后,就可以叫做 公开的,同步化的,无返回值的方法。看到没有,说的是这个方法是同步化的,而不是在说线程。那么就说所谓同步化的方法,说的是这个方法对于所有线程来说,状态是同步的。要理解状态同步,我们先看看不同步的情况是什么样的,对于没有加 synchronized 的方法。
public void method() {
int x = 1;
int y = 2;
int z = 3;
}
如果有两个线程会同时执行这个方法,那么有可能在某一时间点上 A 线程刚执行了 z = 3的操作,而B线程刚执行 x = 1操作。那么从这一时间点上看,这个方法是有两个不同的状态的。这个方法面对A线程和B线程,展现的是两个不同的状态,一个是刚开始进入方法的状态,一个快执行结束了的状态。
所以同步化这个方法,就是强行让这个方法,面对不同线程,必须表现出一致的状态,这个才是同步的本意。那么接下来,我们把这个方法加上synchronized 关键字,看看会怎么样。刚才说了,同步化是要让这个方法对于其他线程表现出一致的状态。那么现在假设, A 正在执行 z = 3 操作。B线程调用方法了,它必须保证不能破坏当前这个方法的状态,那么它选择直接跳到 z = 3去执行?貌似可行?其实不行,因为B如果执行了 z = 3,接着方法返回,这个时候A还没执行完呢。又出现了不一致的情况。所以当B线程发现A线程正在执行这个方法的时候,为了不引起一个不同状态的产生,它必须等待,只有这样才能保证一致性的原则,也就是不能让方法出现两种不同的状态同时存在。
好了,上面是不是不太容易理解。接下来让我们看看现实中的例子吧。下面是电视剧《爱情公寓2》 中的一段,我认为很能说明问题。不知道你有没有看过。
剧情是这样的,左边沙发上的吕子乔,右边的是其他人。他们同时再看另外一个主角曾小贤参加的答题挑战节目。吕子乔一个人头戴耳机,高科技眼镜,自备电脑,完全自闭状态。其他人则一起看电视机。但是呢,吕子乔这边是龟速网络,看同样的节目,比人家延迟好几分钟。于是,当电视那头,曾小贤已经答对了第三题了。吕子乔突然跳起来,高呼:“他居然第一题就把观众求助的机会用掉了的”。而实际上,这已经是几分钟以前的事情了。于是众人听到后,纷纷向他投以关切的目光。
上述剧情中,我们仔细研究就会发现。由于电视信号的延时,吕子乔和其他人看到的节目是不同步的。也就是说,同一电视节目在面对吕子乔和其他人的时候,表现除了不同的状态。试想,如果吕子乔自己一个人躲在房间里看,不和别人交流,那么也没什么问题。这也是大部分方法不需要同步化的原因。不巧的是,吕子乔和其他人坐一起了,他还高呼了那么一句,这就很尴尬了。所以为了避免吕子乔的这种尴尬,电视台说,先给吕子乔的信号掐掉,让他等着,等其他人看完了再给他看。这样一来,其他人看节目的时候,吕子乔还在等待状态,就不会高呼:“他居然第一题就把观众求助的机会用掉了的”这句话,也就不会引来异样的眼光了。