synchronized(修饰方法和代码块)

1. 含义

  • synchronized 是同步锁,用来实现互斥同步。

  • 在 Java 中,关键字 synchronized 可以保证在同一个时刻,只有一个线程可以执行某个方法或者某个代码块(主要是对方法或者代码块中存在共享数据的操作)。

  • synchronized 还可以保证一个线程的变化(主要是共享数据的变化)被其他线程所看到(保证可见性,完全可以替代 volatile 功能,但是 volatile 更轻量,还是要分场景使用)。


2. 用法

synchronized 包括三种用法:

  • 修饰实例方法
  • 修饰静态方法
  • 修饰代码块

2.1 修饰实例方法

所谓的实例对象锁就是用 synchronized 修饰实例对象中的实例方法,注意是实例方法不包括静态方法,如下:

public synchronized void increase() {
i++;
}

2.2 修饰静态方法

当 synchronized 作用于静态方法时,其锁就是当前类的 class 对象锁。由于静态成员不专属于任何一个实例对象,是类成员,因此通过 class 对象锁可以控制静态成员的并发操作。需要注意的是如果一个线程 A 调用一个实例对象的非 static synchronized 方法,而线程 B 需要调用这个实例对象所属类的静态 synchronized 方法,是允许的,不会发生互斥现象,因为访问静态 synchronized 方法占用的锁是当前类的 class 对象,而访问非静态 synchronized 方法占用的锁是当前实例对象锁,二者的锁并不一样,所以不冲突。

public static synchronized void increase() {
i++;
}

2.3 修饰代码块

在某些情况下,我们编写的方法体可能比较大,同时存在一些比较耗时的操作,而需要同步的代码又只有一小部分,如果直接对整个方法进行同步操作,可能会得不偿失,此时我们可以使用同步代码块的方法对需要同步的代码进行包裹,这样就无需对整个方法进行同步操作了。

我们可以使用如下几种对象来作为锁的对象:

成员锁

锁的对象是变量

public Object synMethod(Object a1) {
synchronized(a1) {
// 操作
}
}
实例对象锁

this 代表当前实例

synchronized(this) {
for (int j = 0; j < 100; j++) {
i++;
}
}
当前类的 class 对象锁
synchronized(AccountingSync.class) {
for (int j = 0; j < 100; j++) {
i++;
}
}

3. 什么是可重入锁

含义

所谓可重入锁,指的是以线程为单位,当一个线程获取对象锁之后,这个线程可以再次获取本对象上的锁,而其他的线程是不可以的。(同一个加锁线程自己调用自己不会发生死锁情况)

意义

防止死锁。

实现原理

通过为每个锁关联一个请求计数和一个占有它的线程。当计数为 0 时,认为锁是未被占有的。线程请求一个未被占有的锁时,jvm 将记录锁的占有者,并且将请求计数器置为 1 。如果同一个线程再次请求这个锁,计数将递增;每次占用线程退出同步块,计数器值将递减。直到计数器为0,锁被释放。

应用

synchronized 和 ReentrantLock 都是可重入锁。

ReentrantLock 表现为 API 层面的互斥锁(lock() 和 unlock() 方法配合 try/finally 语句块来完成),synchronized 表现为原生语法层面的互斥锁。


4. 互斥同步的缺点

互斥同步最主要的问题就是进行线程阻塞和唤醒所带来的性能问题,因此这种同步也被称为阻塞同步。而且加锁方式属于悲观锁(不管操作是否成功都加锁)。


5. 参考

synchronized(修饰方法和代码块)的更多相关文章

  1. synchronized修饰方法和代码块的区别

    先看一段代码 Class A { public synchronized methodA() {//对当前对象加锁 } public methodB() { synchronized(this){}/ ...

  2. 【synchronized锁】通过synchronized锁 反编译查看字节码指令分析synchronized关键字修饰方法与代码块的区别

    前提: 首先要铺垫几个前置的知识: Java中的锁如sychronize锁是对象锁,Java对象头中具有标识位,当对象锁升级为重量级锁时,重量级锁的标识位会指向监视器monitor, 而每个Java对 ...

  3. 一张图讲解对象锁和关键字synchronized修饰方法

    每个对象在出生的时候就有一把钥匙(监视器),那么被synchronized 修饰的方法相当于给方法加了一个锁,这个方法就可以进行同步,在多线程的时候,不会出现线程安全问题. 下面通过一张图片进行讲解: ...

  4. JAVA 同步之 synchronized 修饰方法

    在JAVA多线程编程中,将需要并发执行的代码放在Thread类的run方法里面,然后创建多个Thread类的对象,调用start()方法,线程启动执行. 当某段代码需要互斥时,可以用 synchron ...

  5. synchronized修饰方法和对象的区别

    使用synchronized(object) { 代码块.... } 能对代码块进行加锁,不允许其他线程访问,其的作用原理是:在object内有一个变量,当有线程进入时,判断是否为0,如果为0,表示可 ...

  6. [Day13]static、final、匿名对象、内部类、包、修饰符、代码块

    1.final-最终 (1)final的特点 final修饰类不可以被继承,但是可以继承其他类 final修饰的方法不可以被覆盖,但父类中没有final修饰方法,子类覆盖后可以加final final ...

  7. Java面向对象(static、final、匿名对象、内部类、包、修饰符、代码块)

    面向对象 今日内容介绍 u final u static u 匿名对象 u 内部类 u 包的声明与访问 u 四种访问修饰符 u 代码块 第1章 final关键字 1.1 final的概念 继承的出现提 ...

  8. IOS中在自定义控件(非视图控制器)的视图跳转中 代理方法与代码块的比较

    //代码块与代替代理的设计方法 我就以在自定义视图中(非视图控制器,不能实现视图控制功能),通过代理和代码块两种方法分别实现视图的跳转,进行对比 首先自定义了一个视图,上面有一个已经注册了得BUtto ...

  9. Java 悲观锁 synchronized (member){代码块}

    Java 如果遇到会出现高并发的情况,一般建议使用悲观锁 :synchronized (member){代码块}  需要对数据库进行修改或新增的时候,建议写上事务--@Transactional @T ...

随机推荐

  1. NB-IOT技术学习问题记录

    1. TAU是什么,跟踪区更新 2. 小区和基站的区别 3. 附着和设备注册的关系? 4. 不携带PDN是什么意思? 5. PLMN 公共陆地移动网络,和小区的关系,区别?

  2. 【视频开发】关于FFMPEG中内存泄漏的问题之av_bitstream_filter_filter

    How may I free pkt in an ffmpeg write frame method Rate this:      See more: C++ ffmpeg Greetings I' ...

  3. 【神经网络与深度学习】【计算机视觉】SPPNet-引入空间金字塔池化改进RCNN

    转自: https://zhuanlan.zhihu.com/p/24774302?refer=xiaoleimlnote 继续总结一下RCNN系列.上篇RCNN- 将CNN引入目标检测的开山之作 介 ...

  4. postgresql数据库中多个Schemas互相访问

    背景: 用postgresql创建了一个数据库userDataBase,在这个数据库中创建了Schemas userA,Schemas userB,Schemas userC三个Schemas之后,给 ...

  5. PLSQL Developer 11 使用技巧(持续更新)

    PLSQL Developer 11 使用技巧 (持续更新) 目录(?)[-] 首先是我的颜色配置 常用快捷键 提升PLSQL编程效率 按空格自动替换 关闭Window窗口 PLSQL 实用技巧 TI ...

  6. ply2obj

    """ Simple script to convert ply to obj models """ import os from argp ...

  7. windows10 ubuntu子系统运行docker出现的问题

    前一篇笔记记录了安装的过程及错误处理办法,但是在正式使用docker时,却又出现新的问题: “docker: Cannot connect to the Docker daemon at unix:/ ...

  8. react-native-typescript-项目环境搭建

    1.yarn global add create-react-native-app //全局安装 2.create-react-native-app 项目名称 3.yarn add typescrip ...

  9. 使用命令进行Apache Kafka操作

    1.目标 我们可以在Kafka集群上执行几个Apache Kafka Operations .因此,在本文中,我们将详细讨论所有Apache Kafka操作.它还包括有助于实现这些Kafka操作的命令 ...

  10. SAS学习笔记62 通过压缩变量长度来实现数据集压缩

    有时候从其他数据库过来的字符型变量Length很长,导致数据集文件很大,可以通过压缩变量长度来实现数据集压缩 具体思路: LENGTH语句设置所有变量真实长度 SET数据集的时候对原有变量进行RENA ...