文章目录
对象锁,方法锁,类锁区别总结
此小结主要是针对本人对单利设计模式的补充总结,所以有不全面的地方请谅解
内置锁
每个对象都可作为一个实现同步的锁,这些锁就是内置锁
内置锁是一个互斥锁,当A线程(第一个线程)持有内置锁时,B线程(第二个线程)必须等待或者阻塞,直到A线程释放这个锁时,B线程才有机会获得这个锁,所以最多只有一个线程能够获得该锁!
对象锁(synchronized修饰方法或代码块)
其实对象锁就是类中非静态方法上的锁,用 “this” 作为锁
----->原因分析可见”多线程中同步函数的对象锁是this原因分析“
代码一(方法锁形式):
package test1;
public class Lazy {
public synchronized void Method_1()
{
System.out.println("俺是方法锁");
}
}
代码二(代码块形式):
package test1;
public class Lazy {
public void Method_2()
{
synchronized(this)
{
System.out.println("俺是对象锁");
}
}
}
通过上面的代码我们可以清晰的发现,方法锁就是对象锁,只是和代码块这样的形式不同罢了
类锁(synchronized 修饰静态的方法或代码块)
类锁也就是类中静态方法上的锁,用 “类名.class” 做为锁,话不多说,上代码!
代码一(静态方法锁形式):
package test1;
public class Lazy {
public static synchronized void Method_3() //注意多了一个static
{
System.out.println("俺是类锁");
}
}
代码二(代码块形式):
package test1;
public class Lazy {
public static void Method_4() //注意多了一个static
{
synchronized(Lazy.class)
{
System.out.println("俺是类锁");
}
}
}
总的来说,其实就是分是在静态方法还是在非静态方法前面加synchronized关键字,如果是在静态方法前加synchronized,那么它就是类锁,反之另外一种就是对象锁(方法锁),只不过是他们都有各自对应的代码块表现形式而已
引用对象作为锁
看完上面的总结,应该会有一些看过以下代码的小伙伴感到疑惑,说:“这是个啥?”
package test1;
public class Lazy {
Object obj = new Object();
public void Method()
{
synchronized(obj)
{
System.out.println("俺是引用对象作为锁");
}
}
}
其实很简单,我们在对某个对象进行同步时,需要将某个对象添加到锁的引用中,这个锁可以是对象本身(this),也可以是自定义的私有锁(obj),这样的话应该比较好理解
对象锁与类锁的对比
对象锁(与类锁前两点对应)
- 是对于对象实例方法,或者一个对象实例
- 每个类可以有多个对象锁(因为类的对象实例可以有多个),并且不同对象实例的对象锁是互不干扰的
- 一个类的对象锁与另一个类的对象锁是没有关联的,当一个线程获得A类的对象锁,同时也可以获得B类的对象锁
类锁
- 是用于类的静态方法,或者一个类的class对象
- 每个类只有一个类锁(因为每个类只有一个class对象)
- 类锁并不真实存在,只是一种概念上的东西,只是帮助我们理解锁定实例方法和静态方法的区别
总结
synchronized修饰(非静态)方法和synchronized(this)都是锁住自己本身的对象;synchronized修饰静态方法和synchronized(类名.class)都是锁住加载类对象;synchronized(object)是锁住object对象
还有一些更深层次的总结内容可以移步至“相关优秀博客”