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

  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关键字创建的字符串对象可以安全使用。

欢迎关注我的博客,里面有很多精品合集

  • 本文转载注明出处(必须带连接,不能只转文字):字母哥博客

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

Java synchronized对象级别与类级别的同步锁的更多相关文章

  1. 理解Java中对象基础Object类

    一.Object简述 源码注释:Object类是所有类层级关系的Root节点,作为所有类的超类,包括数组也实现了该类的方法,注意这里说的很明确,指类层面. 所以在Java中有一句常说的话,一切皆对象, ...

  2. Java匿名对象和匿名类总结

    一.匿名对象 匿名对象是没有名字的实体,也就是该实体没有对应的变量名引用  匿名对象的特征:            创建的匿名类的对象只能够调用一次            匿名对象只在堆内存中开辟空间 ...

  3. Java Synchronized的用法

    synchronized是Java中的关键字,是一种同步锁.它修饰的对象有以下几种: 1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码 ...

  4. JAVA Synchronized (一)

    <编程思想之多线程与多进程(1)——以操作系统的角度述说线程与进程>一文详细讲述了线程.进程的关系及在操作系统中的表现,这是多线程学习必须了解的基础.本文将接着讲一下Java线程同步中的一 ...

  5. Java多线程同步锁的理解

    java主要通过synchronized的关键字来实现的.让我们从一个买票程序说起吧. package com.day04; /** * * @author Administrator 问题描述:使用 ...

  6. 对象级别锁 vs 类级别锁 – Java

    同步针对的是多线程.同步的方法或代码块同时只能由一个线程执行. Java支持多线程来执行.这可能会导致两个或多个线程访问同一个字段或对象.同步是一个使所有并发执行的线程同步的过程.同步避免了由于共享内 ...

  7. 对象级别锁 vs 类级别锁(Java)

    前言 对于多线程(并发)和Spring Boot这两块在同步进行学习中,在看到使用synchronized关键字使操作同步时,看到和C#中不一样的东西,所以这里呢,就深入学习了下,若有错误之处,还望指 ...

  8. synchronized 线程同步-类级别锁定

    1.demo 说明:代码中通过 printNum 方法传入参数判断 a.b 分别对 num 这个参数的值进行了修改. package demo1; import sun.applet.Main; pu ...

  9. jQuery插件开发全解析,类级别与对象级别开发

    jQuery插件的开发包括两种: 一种是类级别的插件开发,即给jQuery添加新的全局函数,相当于给jQuery类本身添加方法.jQuery的全局函数就是属于jQuery命名空间的函数,另一种是对象级 ...

随机推荐

  1. Codeforces Round #697 (Div. 3)

    A.Odd Divisor 题意:问一个数是不是含有奇数因子 思路:就直接给这个数循环除以2,看看最后剩下的数是不是0,如果不是就有奇数因子,如果是就没有 想不到:1)当时想着用log2来解决问题,后 ...

  2. Java初始化数据域的途径

    Java调用构造器的具体处理步骤: 1.所有数据域被初始化为默认值(0,false或null); 2.按照在类声明中出现的次序,依次执行所有域的初始化语句和初始化块: 3.如果构造器第一行调用了第二个 ...

  3. 拷贝构造函数第一个参数最好使用const

    拷贝构造函数的第一个参数要求是自身类型的引用,但是没有一定要求具有底层const属性即对常量的引用,但是使用时最好加上const,原因是我们可能在某些"不知道"的情况下对常量对象调 ...

  4. .NET程序崩溃了怎么抓 Dump ? 我总结了三种方案

    一:背景 1. 讲故事 最近几天接到了几个crash的求助,可能这几个朋友没玩过怎么去生成dump,只能手把手教,感觉也不是一个办法,所以有必要总结一下,后续再有朋友咨询的话,我就可以把这篇文章丢过去 ...

  5. [Python] Tkinter command

    例1:创建按钮 import tkinter as tk class App: def __init__(self,root): frame = tk.Frame(root) frame.pack() ...

  6. SecureCRT自动保存日志设置

    SecureCRT自动保存日志设置原创杭州_燕十三 最后发布于2017-03-26 22:00:08 阅读数 24731 收藏展开 嵌入式开发经常由于无法debug而只能使用串口打印日志的方式调试代码 ...

  7. zabbix screen 图片以邮件形式发送

    zabbix screen 图片以邮件形式发送 #! /usr/bin/env python #coding=utf-8 # Andy_f import time,os import urllib i ...

  8. 记一次MySQL(5.7版本)数据库的主从同步和备份

    我遇到的问题 我先后在BAT三大云服务器商购买了学生机,配置如下 百度云2核/4G 阿里云1核/2G 腾讯云1核/2G 我的解决方案 由于我不知道百度云的续费规则,导致买了2核/4G的服务器之后以为像 ...

  9. ms5611-01ba03 气压传感器 中英文 数据手册

    中文: https://wenku.baidu.com/view/6f8a861fff00bed5b9f31d53.html 英文: https://wenku.baidu.com/view/fe93 ...

  10. 一个很好的网站 有3D漂浮框 有动态小人数字时钟

    http://www.cnblogs.com/jingmoxukong/p/7867397.html