什么是同步的
如果一个资源被多个线程共享,我们需要同步线程,以避免资源抢占造成的资源数据混乱。在Java中,synchronized是实现线程同步的关键字。
使用synchronized关键字获取Java对象的锁并保护锁定的代码块。JVM保证只有一个线程可以获得Java对象的锁并同时执行相应的代码块,从而实现线程安全。
使用同步
synchronized关键字可用于装饰三个位置:
- 在装饰实例方法中,锁定对象是此对象的当前对象。
- 修饰代码块,即synchronized(object){},lock对象是()中的对象,通常是this或explicit对象。
- 在修改静态方法时,锁对象是方法区域中的类对象和全局锁。
- 修改一个类,即直接影响一个类。
根据同步修改的不同位置,实现原理不同。
从反编译的结果中,我们可以看到sync()方法中还有一个标识符。JVM基于此acc_uuusynchronized标识符来实现方法同步,即:
当执行该方法时,JVM调用该指令来检查是否在方法uuSynchronized identifier上设置了ACC,如果设置了ACCuSynchronized identifier,则将获得锁对象的监控对象。线程执行方法体后,将释放锁对象的监视器对象。在此期间,其他线程无法获取锁对象的监视器对象。
显然,在线程0完成执行之前,线程1不会开始执行。再次检查字节码信息:
我们可以看到sync()字节码指令中有两条monitorenter和monitorexit指令:
Monitorenter:此指令指示要获取锁定对象的监视器对象。此时,监视器对象中的计数将增加+1。如果监视器已被其他线程获取,则该线程将被阻止,直到count=0,然后再次尝试获取监视器对象。
Monitorexit:此指令指示线程释放锁对象的监视器对象。此时,监视器对象的计数将从-1变为0。其他被阻止的线程可以再次尝试获取锁定对象的监视器对象。
您可以看到,与instance方法一样,sync()方法上还有一个标识符。可以得出结论,同步在实例方法上的实现原理与在静态方法上的实现原理相同,两者都是acc_uuu同步标识符来实现。只是它们锁定了不同的对象。