java中Synchronized对象锁和类锁的区别

透彻理解java中Synchronized对象锁和类锁的区别

java内置锁

​ java内置锁:每个java对象都可以用做一个实现同步的锁,这些锁称为内置锁。线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法的时候会释放该锁。获得内置锁的唯一途径就是进入这个锁的保护的同步代码块或方法。

​ java内置锁是一个互斥锁,意味着最多只有一个线程能获取得该锁,当线程A尝试去获取线程B持有的内置锁的时候,线程A必须等待或者阻塞,直到线程B释放这个锁,如果B线程不释放这个锁,那么A线程就会永远等待下去。

​ java的对象锁和类锁:java的对象锁和类锁在概念上基本上和内置锁是一致的。

对象锁和类锁

java对象锁

  • 对象锁是用于对象实例方法,或者一个对象实例上的。若实例对象被lock,则该实例对象的所有同步方法全被lock

java类锁

  • 类锁是用于类的静态方法或者一个类的class对象上的。若类对象被lock,则类对象的所有同步方法全被lock

​ 总体来说,当Synchronized加到static方法前面就是给class加锁,即类锁;而Synchronized加到非静态方法前面是给对象上锁

​ 对象锁和类锁是不同的锁,所以多线程同时执行这两个不同锁的方法时,是异步的。

​ 类锁是同步执行的。对象锁锁的对象不一样,所以是异步执行的。

​ 如果多线程同时访问同一类的类锁以及对象锁,这两个方法执行是异步的,原因:类锁和对象锁是两种不同的锁

​ 类锁对该类的所有对象都能起到作用,而对象锁不能。

Synchronized的缺陷

​ 当某个线程进入同步方法获得对象锁,你们其他线程访问这里对象的同步方法时,必须等待或者阻塞,这会影响性能甚至导致系统崩溃。

​ 这就是同步代码块在某种情况下优于同步方法的方面。当Synchronized修饰代码块的时候,那么这个方法加锁的对象是整个对象,根执行这行代码的对象没有关系,当一个线程执行这个方法时,这对其他同步方法是没有影响的,因为他们持有的锁是完全不一样的。

总结五种用法

1.this

synchronized(this){
    
    
    // 互斥代码
}

这里的this指的是执行这段代码的对象,Synchronized得到的锁就是this这个对象的锁

public synchronized void fun(){
    
    
    // 互斥代码
}

2.A.clsaa

synchronized(A.class){
    
    
    // 互斥代码
}

这里A.class得到的是A这个类,所以Synchronized关键字得到的锁是类的锁,这种方法同下面的方法功能是相同的:

public static synchronized void fun(){
    
    
    // 互斥代码
}

​ 所有需要类的锁的方法都不能同时执行,但是它和需要某个对象的锁的方法或者是不需要任何锁的方法可以同时执行

3.object.getClass()

synchronized(object.getClass){
    
    
    // 互斥代码
}

​ 这种方法一般情况下同第二种,但是出现继承和多态时,得到的结果却是不相同的。所以一般情况下推荐使用A.class的方式

4.Object

private Object lock = new Object();
public void test1(){
    
    
    synchronized(lock){
    
    
        // 互斥代码
    }
}

这里的Synchronized关键字拿到的锁是对象object的锁,所有需要这个对象的锁的方法都不能同时执行。这是最常见的高并发场景下要锁住某个方法所用的操作

5.static object

private static Object lock = new Object();
public void test(){
    
    
    synchronized(lock){
    
    
        // 互斥代码
    }
}

​ 这样不同的类使用的就是同一个objct对象,需要的锁也是同一个锁,就可以达到互斥的效果了

猜你喜欢

转载自blog.csdn.net/issunmingzhi/article/details/107692182