同步代码块和同步方法的区别
同步方法块和同步方法的区别
- 只需要对临界区的代码进行同步
- 在同步代码块中,我们可以自由选择锁
- JVM层面的不同
这个问题,可以理解为在实际开发中,是使用同步代码块好,还是使用同步方法好?
答:同步代码块比同步方法好
只需要对临界区的代码进行同步
我们要清楚实际要同步的临界区,大多数情况下,只是某一段需要同步
当然如果整个方法都需要同步,同步代码块和同步方法其实效果是一样的
在同步代码块中,我们可以自由选择锁
同步代码块中,我们可以自由选择任何一个Java对象实例作为锁;但是同步方法只能是这个对象的实例
这就会带来一个问题,假如我们类中定义了两个不同的实例同步方法,这两个方法在业务上并没有太多关联。
单例情况下,当某个线程在调用其中一个同步方法时,其他线程就无法调用另外一个实例同步方法,必须等到一个实例同步方法执行完成,释放锁,其他线程才能得到锁
如果我们使用的是同步代码块,自由定义锁,这样就可以避免多个同步实例方法彼此之间的影响
JVM层面的不同
1)同步方法,JVM采用ACC_SYNCHRONIZED
标记符来实现同步
详解:
a.方法级的同步是隐式的,同步方法的常量池中会有一个ACC_SYNCHRONIZED
标志。
b.当某个线程要访问某个方法时,会检测是否有ACC_SYNCHRONIZED
,如果有,则需要先获得监视器 锁,然后开始执行方法,方法执行之后再释放监视器锁。
c.这时如果其他线程来请求执行方法,会因为无法获得监视器锁而被阻断
d.如果方法执行过程中,发生异常,并且方法内部没有异常处理,那么在一次呗跑到方法外面之前,监视器锁会被自动释放
2)同步代码块,JVM采用monitorenter
、monitorexit
两个指令来实现同步
详解:
a.可以把执行monitorenter
理解为加锁,执行monitorexit
理解为释放锁
b.每个对象维护着一个记录着被锁次数的计数器,未被锁定的对象的该计数器为0
c.当一个线程获得锁后,该计数器自增1,当同一个线程再次获得该对象的锁时,计数器再次自增
d.当同一个线程释放锁时,计数器再自减。
e.当计数器为0时,锁被释放,其他线程便可以获得锁
还没有评论,来说两句吧...