Java synchronized对象级别与类级别的同步锁

Java synchronized 关键字 能够将一个代码块或一个方法标记为同步代码块。同步代码块是指同一时间只能有一个线程执行的代码,而且执行该代码的线程持有同步锁。synchronized关键字能够做用于vue

  • 一个代码块
  • 一种方法

当一个方法或代码块被声明为synchronized时,若是一个线程正在执行该synchronized 方法或代码块,其余线程会被阻塞,直到持有同步锁的线程释放。根据锁定的范围能够分为spring

  • 类级别的锁能够防止多个线程在运行时同时进入该类全部实例化对象的 synchronized代码块中。
  • 对象级别的锁能够防止多个线程在运行时同时进入当前(或某一个)实例化对象的 synchronized代码块中。

1. 对象级别的同步锁

对象级别的同步锁:当咱们想要在多线程环境下同步执行一个非静态方法或非静态代码块时,在类的方法或代码块加上synchronized关键字,能够保证对象实例级别数据的线程安全。(比较后文的类级别的同步锁,回头来理解这句话)后端

对象级别的加锁的代码以下,如:在方法上加锁,锁对象为当前类的实例化对象安全

public class DemoClass{
    public synchronized void demoMethod(){}
}

如:为代码块加锁,锁对象为this对象springboot

public class DemoClass{
    public void demoMethod(){
        synchronized (this){
            //同步代码块
        }
    }
}

如:为代码块加锁,锁对象为咱们建立的任意一个对象。不要使用非final的成员变量做为同步锁对象,由于非final成员变量能够被从新赋值,致使不一样的线程使用不一样的对象做为锁,达不到同步锁定的效果。多线程

public class DemoClass{
    //注意这里的关键字final很是重要,看说明
    private final Object lock = new Object();
    public void demoMethod(){
        synchronized (lock){
            //同步代码块
        }
    }
}

2. 类级别的同步锁

类级别的锁能够防止多个线程在运行时进入该类全部实例化对象的 "synchronized块中。也就是说若是运行时有100个DemoClass的实例,那么每次只有一个线程可以在任何一个实例中执行demoMethod(),全部其余实例的全部其余线程都被锁定。并发

为了保障静态数据线程安全,应该使用类级别的锁定。咱们知道static关键字将方法的数据关联到类的级别上,因此在静态方法上使用锁。前后端分离

静态方法加锁,对该类全部的实例化对象生效函数

public class DemoClass{
    //静态方法加锁,对该类全部的实例化对象生效
    public synchronized static void demoMethod(){

    }
}

获取 .class类的引用,类级别的锁微服务

public class DemoClass{
    public void demoMethod(){
        //获取 .class类的引用,类级别的锁,对该类全部的实例化对象生效
        synchronized (DemoClass.class){
            //同步代码块
        }
    }
}

使用静态对象的锁,类级别的锁

public class DemoClass{
    //静态对象,类级别,注意这里的关键字final很是重要
    private final static Object lock = new Object();
    public void demoMethod(){
        //使用静态对象的锁,类级别锁,对该类全部的实例化对象生效
        synchronized (lock){
            //同步代码块
        }
    }
}

3. 总结

  1. Java中的同步机制保证了两个或多个线程没法同时执行一个须要相同同步锁的方法。
  2. "synchronized "关键字只能用于方法和代码块。这些方法或代码块能够是静态非静态的。
  3. 当一个线程进入synchronized方法或代码块时,它就会得到一个锁,当它离开同步方法或代码块时,它就会释放这个锁。若是线程执行过程出现任何错误或异常,锁也会被释放。
  4. 使用"synchronized "关键字持有的锁在本质上是可重入的,这意味着若是一个同步方法调用另外一个使用相同锁的同步方法,那么持有锁的当前线程能够进入该方法而无需再次得到锁。
  5. 若是同步块中使用的对象为空,Java synchronized 将抛出NullPointerException
  6. 使用synchronized同步方法会给你的应用程序带来性能成本。所以,尽可能在绝对须要的状况下才使用同步。另外优先考虑使用同步代码块,而且只同步代码的关键部分。
  7. 静态同步方法和非静态同步方法有可能同时或并发运行,由于它们使用的是不一样的锁。
  8. 根据Java语言规范,你不能在构造函数中使用synchronized关键字。这是不合法的,会致使编译错误。
  9. 不要使用非final的成员变量做为同步锁对象,由于非final成员变量能够被从新赋值,致使不一样的线程使用不一样的对象做为锁,达不到同步锁定的效果。
  10. 不要使用字符串字面量做为锁对象,如:String a = "1";,由于它们可能会被应用程序中的其余地方引用,并可能致使死锁。用new关键字建立的字符串对象能够安全使用。

    欢迎关注个人博客,里面有不少精品合集

本文转载注明出处(必须带链接,不能只转文字):字母哥博客 - zimug.com

以为对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创做动力! 。另外,笔者最近一段时间输出了以下的精品内容,期待您的关注。

相关文章
相关标签/搜索