Java对象级别与类级别的同步锁synchronized语法示例

作者:字母哥哥 时间:2023-06-25 09:11:22 

Java对象级别与类级别的同步锁synchronized语法示例

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

  • 一个代码块

  • 一种方法

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

  • 类级别的锁可以防止多个线程在运行时同时进入该类所有实例化对象的 synchronized代码块中。

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

1. 对象级别的同步锁

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

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

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

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

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. 总结

  • Java中的同步机制保证了两个或多个线程无法同时执行一个需要相同同步锁的方法。

  • "synchronized "关键字只能用于方法和代码块。这些方法或代码块可以是静态或非静态的。

  • 当一个线程进入synchronized方法或代码块时,它就会获得一个锁,当它离开同步方法或代码块时,它就会释放这个锁。如果线程执行过程出现任何错误或异常,锁也会被释放。

  • 使用"synchronized "关键字持有的锁在本质上是可重入的,这意味着如果一个同步方法调用另一个使用相同锁的同步方法,那么持有锁的当前线程可以进入该方法而无需再次获得锁。

  • 如果同步块中使用的对象为空,Java synchronized 将抛出NullPointerException

  • 使用synchronized同步方法会给你的应用程序带来性能成本。因此,尽量在绝对需要的情况下才使用同步。另外优先考虑使用同步代码块,并且只同步代码的关键部分。

  • 静态同步方法和非静态同步方法有可能同时或并发运行,因为它们使用的是不同的锁。

  • 根据Java语言规范,你不能在构造函数中使用synchronized关键字。这是不合法的,会导致编译错误。

  • 不要使用非final的成员变量作为同步锁对象,因为非final成员变量可以被重新赋值,导致不同的线程使用不同的对象作为锁,达不到同步锁定的效果。

  • 不要使用字符串字面量作为锁对象,如:String a = "1";,因为它们可能会被应用程序中的其他地方引用,并可能导致死锁。用new关键字创建的字符串对象可以安全使用。

来源:https://zimug.blog.csdn.net/article/details/116142822

标签:对象,类,同步锁,synchronized
0
投稿

猜你喜欢

  • C# Winform 实现控件自适应父容器大小的示例代码

    2021-06-15 20:00:52
  • Android Studio 2022.1.1创建项目的Gradle配置问题

    2022-05-05 21:45:36
  • C++ Boost MPI接口详细讲解

    2023-11-02 13:35:36
  • Android编程实现将应用强制安装到手机内存的方法

    2022-09-09 23:02:08
  • Java concurrency线程池之线程池原理(二)_动力节点Java学院整理

    2023-11-28 23:43:18
  • C#中Dispose和Finalize方法使用介绍

    2022-09-10 16:05:21
  • C# lambda表达式原理定义及实例详解

    2021-07-26 21:44:44
  • OpenXml读写Excel实例代码

    2023-09-10 18:11:22
  • Java二分查找算法与数组处理的应用实例

    2022-07-11 01:26:57
  • windows下jar包开机自动重启的步骤

    2022-10-17 22:21:41
  • 详解JS与APP原生控件交互

    2022-11-21 21:28:15
  • maven资源过滤打包后文件变大的处理方法

    2023-10-05 21:38:24
  • Android 使用Picasso加载网络图片等比例缩放的实现方法

    2023-08-29 15:36:32
  • maven工程中jar包瘦身的五种方法

    2023-11-04 05:01:54
  • C#算法之各位相加

    2021-09-03 17:32:42
  • Javassist如何操作Java 字节码

    2021-08-09 08:21:28
  • C#端口扫描器的编写方法

    2023-12-17 17:47:24
  • java数据结构和算法学习之汉诺塔示例

    2021-09-28 14:46:18
  • Java8深入学习之熟透Optional

    2023-08-24 21:27:54
  • Java实现上传文件图片到指定服务器目录

    2023-06-28 00:23:32
  • asp之家 软件编程 m.aspxhome.com