1、线程同步的意义。
线程的同步是为了保证代码的原子性,保证每个线程在调用对象同步方法独占的方法操作该对象。一段代码就好像一座独木桥,任何一个时刻,只能有一个人在桥上行走,程序中不能有多个线程同时在这两句代码之间执行,这就是线程同步。比如:银行的自动柜员机,一次只能一个人取钱,其他人必须排队。公司的打印机虽然是多台电脑共用的,但是每次也只能一台电脑在打印。
同步是以牺牲程序的性能为代价的。所以,如果确定程序没有安全性的问题,就没有必要使用同步。
2、同步的实现,使用synchronize关键字
我们将需要具有原子性的代码放入synchronize语句内,形成同步代码块。就可以保证线程安全了。每个对象都有一个标志位(锁旗标),该标志位有两个状态0、1,其开始状态为1,当执行synchronized(Object)语句后,Object对象的标志位变为0状态,直到执行完整个synchronized语句中的代码块后才又回到1状态。
一个线程执行到synchronized(Object)的时候,先检查Object对象的标志位,0表示有线程在执行,这个线程将暂时阻塞,让出CPU资源,直到另外线程执行完有关代码,将Object对象状态恢复到1状态,这个阻塞才被取消,然后线程开始执行,同时将Object对象的标志位变为0,防止其他线程再进入有关的同步代码块中。
当线程执行到synchronized的时候,如果得不到锁标记,这个线程会被加入到一个与该对象的锁标记相关连的等待线程池当中,等待锁标记。当线程执行完同步代码,就会释放锁标记。
synchronized有两种用法
(1)定义同步方法: synchronized 方法名称(同步){ 方法体 } ,使用这个方法对象都会同步。
(2)同步块,灵活锁住对象同步方法就等于锁住this:synchronized(对象){ 同步块 }