多线程--对象锁与类锁的区别

多线程--对象锁与类锁的区别

对象锁

对象锁:java中任何对象都拥有一个互斥锁,当一个类中声明了synchronized方法,或者在方法中声明了参考(reference)对象为this的synchronized代码块
则表示在此方法或者此代码块中该对象同时只能被同一个线程访问。
例如类A有一个同步方法f1(),a1、a2两个实例对象
当一个线程t1通过a1调用f1()时,此时t1拥有对象a1的锁,与此同时:
1.当其他线程再次通过a1来调用f1时,此时需要等待t1将a1的锁释放才能进入,此时为阻塞状态。
2.当线程t2通过a2来调用f1()时,是不会阻塞的,因为t1只是持有了a1的锁并没有持有a2的锁。

类锁

类锁:java中类的所有实例化对象都属于该类的class对象,当一个类中,拥有同步静态方法,或者同步代码块使用类名.class修饰,那么当前类只能同时被一个对象持有类锁。此时该类的静态成员,静态方法,因为都从属于该类,所有只能同时被一个该类实例对象访问。

由于一个class不论被实例化多少次,其中的静态方法和静态变量在内存中都只有一份。所以,一旦一个静态的方法被申明为synchronized。此类所有的实例化对象在调用此方法,共用同一把锁,我们称之为类锁。

小结

对象锁用来控制实例方法之间的同步,类锁是用来控制静态方法(或静态变量互斥体)之间的同步。
 
对于类锁,会把整个类锁住,也就说只能有一个对象拥有当前类的锁。当一个对象拥有了类锁之后,另外一个对象还想竞争锁的话则会被阻塞。
两个对象A,B,如果A正在访问一个被类锁修饰的方法function,那么B则不能访问。因为类锁只能在同一时刻被一个对象拥有。相对于对象锁,则不同:还是A,B两个对象,如果A正在访问对象锁修饰的function,那么这个时候B也可以同时访问。

对象锁(方法锁),是针对一个对象的,它只在该对象的某个内存位置声明一个标识该对象是否拥有锁,所以它只会锁住当前的对象,一般一个对象锁是对一个非静态成员变量进行synchronized修饰,或者对一个非静态成员方法进行synchronized进行修饰,对于对象锁,不同对象访问同一个被synchronized修饰的方法的时候不会阻塞

拓展–可重入锁

可重入锁:对于对象锁,当一个对象拥有锁之后,访问一个加了对象锁的方法,而该方法中又调用了该类中其他加了对象锁的方法,那么这个时候是不会阻塞住的。

这是java通过可重入锁机制实现的。可重入锁指的是当一个对象拥有对象锁之后,可以重复获取该锁。因为synchronized块是可重入的,所以当你访问一个对象锁的方法的时候,在该方法中继续访问其他对象锁方法是不会被阻塞的。

发布了27 篇原创文章 · 获赞 27 · 访问量 4290

猜你喜欢

转载自blog.csdn.net/qq_41788977/article/details/100591873