线程基础知识(三)

前言

之前两篇文章介绍了线程的基本概念和锁的基本知识,本文主要是学习同步机制,包括使用synchronized关键字、ReentrantLock等,了解锁的种类,死锁、竞争条件等并发编程中常见的问题。

关键字synchronized

  1. synchronied关键字可以把任意一个非null的对象当做锁,属于独占式的悲观锁。同时属于可重入锁
  2. 早期的的synchronized属于重量级的锁,效率低下,因为监视器是依赖底层的操作系统Lock实现的,从6之后java对sychronized进行了优化,jdk1.6以后还引入了 大量的优化,比如自旋锁,适应性锁,锁消除,锁粗化,偏向锁,轻量级锁等。

synchronized用法

常用来保证代码的原子性,主要有三种使用方法

  • 修饰实例:作用于当前的对象实例加锁,进入同步代码前获得,当前对象实例的锁
synchronized void method() {
//业务代码
}
  • 修饰静态方法: 也就是给当前类加锁,会作用于该类所有的对象实例。如果线程A调用一个实例对象的非静态synchronized方法,而线程B需要调用这个实例对象所属类的静态synchronized方法,是允许的,不会发生互斥现象,因为静态synchronized方法是占用的锁是当前类的锁,而访问非静态synchronized方法占用的锁是当前实例对象的锁。
synchronized void staic method() {
//业务代码
}
  • 修饰代码块: 指定加锁对象,对给定的对象/类加锁,synchronized(this object)表示进入同步前要获得给定对象的锁,synchronized(类.class)表示进入同步前要获得给定类class的锁
synchronized(this) {
//业务代码
}

synchronized实现原理

  • 使用synchronized是不用我们去加锁和释放lock,unlock,是jvm已经代替去做了
  • synchronized修饰代码块的时候,jvm是使用monitorenter和monitorexit两个指令实现的(监视器)
    在这里插入图片描述
  • 当修饰同步方法,jvm采用ACC_SYNCHRONIZED标记符来实现的同步, 这个标识表面了这是一个同步方法

在这里插入图片描述

synchronized锁住的原理

monitorenter,monitorexit,ACC_SYNCHRONIZED都是基于monitor(监视器)
所谓的Monitor其实是一种同步工具,也可以说是一种同步机制。在Java虚拟机(HotSpot)中,Monitor是由
ObjectMonitor实现的,可以叫做内部锁,或者Monitor锁。
ObjectMonitor的工作原理:
ObjectMonitor有两个队列:WaitSet、EntryList,用来保存ObjectWaiter 对象列表。
_owner,获取 Monitor 对象的线程进入 _owner 区时, _count + 1。如果线程调用了wait() 方法,此时会释放Monitor 对象, _owner 恢复为空, _count - 1。同时该等待线程进入 _WaitSet 中,等待被唤醒。
-同步是锁住的

  • monitorenter,在判断拥有同步标识 ACC_SYNCHRONIZED 抢先进入此方法的线程会优先拥有 Monitor 的owner ,此时计数器+1。
  • monitorexit,当执行完退出后,计数器-1,归 0 后被其他进入的线程获得

除了原子性,synchronized的可见性和有序性,可重入性怎么实现

  1. 可见性:线程加锁前,将清空工作内存中共享变量的值,从而使用共享变量的时候,需要从主内存中重新读取最新的值。线程加锁后,其他线程无法获得主内存中的共享变量的值,线程解锁前必须把共享变量的最新值刷新到主内存中。
  2. 有序性:synchronized同步的代码块具有排他性,一次只能被一个线程拥有,所以可以保证同一个时刻,代码是单线程执行的,因为as-if-serial存在,单线程语句是能够保证最终结果是有序的,但是不保证不会进行指令重排,所以synchronized是保证有序是执行结果的有序而不是防止指令重排的有序性。
  3. 可重入性:synchronized是可重入锁,也就说允许一个线程二次请求自己持有的锁的临界资源,这种情况就是可重入锁,锁对象有个计数器,会记录线程获取锁的次数,当执行完对应的代码后,计数器就会减去1,只有归零就会释放锁。之所以可以重入就是因为这个计数器。

synchronized和ReentrantLock的区别

可从锁的实现、功能特点、性能维度等分析

  • 锁的实现:synchronized是通过jvm实现,是java的关键字;而reentrantlock是通过jdk层面的api实现的的(一般是lock()和unlock()方法配合try/catch/finally语句实现)

  • 性能:jdk1.6前synchronized性能比较差,应该都是要通过底层调用,但是1.6以后增加了适应性自旋,锁消除等,两者性能差不多。

  • 功能特点:-

    • ReentrantLock比synchronized增加了一些高级功能,如等待中断,可实现公平锁,可实现选择性通知;
    • synchronized只能是非公平锁(内部锁),- ReentrantLock可以指定是公平还是非公平(公平锁就是先等待的线程先获得锁);
    • synchronized与wait()和notify()/notifyAll()方法结合实现等待/通知机制,ReentrantLock类借助Condition接口与newCondition()方法实现。
    • ReentrantLock需要手工声明来加锁和释放锁,一般跟finally配合释放锁。而synchronized不用手动释放锁

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/305544.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

「Kafka」生产者篇

「Kafka」生产者篇 生产者发送消息流程 在消息发送的过程中,涉及到了 两个线程 ——main 线程和Sender 线程。 在 main 线程中创建了 一个 双端队列 RecordAccumulator。 main线程将消息发送给RecordAccumulator,Sender线程不断从 RecordAccumulator…

独立容器 Rancher Server 证书过期解决

问题 Rancher无法登录 容器报错X509:certificate has expired or is not ye valid 在某天需要发布新版本的时候,发现rancher无法登录,于是到服务器上查看rancher日志,发现以下内容: docker logs -f rancher --since10…

基于遗传算法的航线规划

MATLAB2016b可以正常运行 基于遗传算法的无人机航线规划资源-CSDN文库

k8s二进制部署--部署高可用

连接上文 notready是因为没有网络,因此无法创建pod k8s的CNI网络插件模式 1.pod内部,容器与容器之间的通信。 在同一个pod中的容器共享资源和网络,使用同一个网络命名空间。 2.同一个node节点之内,不同pod之间的通信。 每个pod都…

SQL Server 索引和视图

CSDN 成就一亿技术人! 难度指数:* * * CSDN 成就一亿技术人! 目录 1.索引 什么是索引? 索引的作用? 索引的分类 1. 唯一索引 2. 主键索引 3. 聚集索引 4.非聚集索引 5.复合索引 6.全文搜索 索引的创建&am…

【Vulnhub 靶场】【Looz: 1】【简单】【20210802】

1、环境介绍 靶场介绍:https://www.vulnhub.com/entry/looz-1,732/ 靶场下载:https://download.vulnhub.com/looz/Looz.zip 靶场难度:简单 发布日期:2021年08月02日 文件大小:2.1 GB 靶场作者:mhz_cyber &…

【网络安全 | Misc】世安杯 适合作为桌面(Stegsolve及Winhex的使用)

正文 解压后得到图片: 图片属性正常,无特殊点,经测试,无隐写文件: Stegsolve 运行方法: 可以看到出现二维码: 对其解密得到: 03F30D0A79CB05586300000000000000000100000040000000…

记录一下亿级别数据入库clickhouse

需求背景 公司的业务主要是广告数据归因的,每天的pv数据和加粉数据粗粗算一下,一天几千万上亿是有的。由于数据量大,客户在后台查询时间跨度比较大的数据时,查询效率就堪忧。因而将数据聚合后导到clickhouse进行存储,…

pybullet安装时出现fatal error C1083: 无法打开包括文件: “string.h”: No such file or directory

pybullet安装时出现fatal error C1083: 无法打开包括文件: “string.h”: No such file or directory 报错原文: -----CloneTreeCreator.cppD:\Program_Professional\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.38.33130\include\cstring(11): fat…

用C语言写爬虫程序采集美图录图片

最近有个公司找我,说他们在某图库充值会员,想要使用里面的图片,而是是海量,问我有没有办法做个筛选并下载保存,成了给我包个大红包。这事有啥难得,以我现在的专业知识储备,这种事情分分钟就解决…

打开相机失败 出现错误的原因

如何解决? Debug中缺少DLL文件 以下参考周姐文档 相机调用步骤 学习相机第三方库的安装 https://blog.csdn.net/Qingshan_z/article/details/117257136书签:QT添加库(静态库和动态库)_Qingshan_z的博客-CSDN博客_qt添加库 添加文…

九九乘法表c 语言 用于打印九九乘法表

以下是一个简单的C语言程序&#xff0c;用于打印九九乘法表&#xff1a; #include <stdio.h>int main() {int i, j;for (i 1; i < 9; i) {for (j 1; j < i; j) {printf("%d*%d%-2d ", j, i, i*j);}printf("\n");}return 0; }解释&#xff1…