Java工作线程 主存 同步机制_Java 并发变成同步机制

2023-10-29

并发编程的演进:

批处理——多进程——多线程

在多线程变成中,由于多个线程共享进程的变量,有可能出现同时访问一个资源的情况,因此需要使用同步机制。

java的内存模型:

Java内存模型规定所有的变量都存在主存当中,每个线程都有自己的工作内存,线程对变量的所有操作都必须在工作内存中进行,而不能直接在主存进行操作。并且每个线程不能访问其他线程的工作内存。

关键字:

原子操作:原子为不可再分操作。只有对象的读取和赋值是原子操作。int i=10 是原子操作。int x = y;不是原子操作

violation:可见关键字

Synchronized:内部隐示锁

lock: ReentrantLock(显示锁) + ReentrantReadWriteLock(读写锁)

violation关键字:

一旦一个共享变量被volatile修饰之后,那么就具备了两层含义。

1)可见性:  保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

它会强制将对缓存的修改操作立即写入主存,同时会导致其他CPU对应的缓存无效。

通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中

2) 有序性: 禁止进行指令重排序。

需要注意的是violation不保证原子性。

比如:

publicvolatileintinc =0;

inc++;

在多线程中不同依靠violation关键字保证原子操作。

使用volatile关键字的场景:

1) 多变量的写操作不依赖于当前值

2) 该变量没有包含在具有其他变量的不变式中。

使用例子:状态标记量:

volatile boolean inited = false;

//线程1:

context = loadContext();

inited = true;

//线程2:

while(!inited ){

sleep()

}

doSomethingwithconfig(context);

synchronized:

把一些不是原子操作组合成原子操作。

(1) synchronized方法

示例代码:

public class InsertData {

public synchronized void insert(){

for(int i=0; i<10;++i){

System.out.println(Thread.currentThread().getName() + ": 执行,变量i = "+i);

}

}

public synchronized void insert2() {

System.out.println(Thread.currentThread().getName()+ "start inset2");

try {

Thread.sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+ "end inset2");

}

public static synchronized void insert3(){

System.out.println(Thread.currentThread().getName() + "insert3");

}

public void insert4(){

System.out.println(Thread.currentThread().getName()+"insert4");

}

}测试代码:

public class SynTest {

@Test

public void test() throws InterruptedException {

InsertData insertData = new InsertData();

new Thread(new Runnable() {

@Override

public void run() {

insertData.insert();

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

insertData.insert();

}

}).start();

Thread.sleep(8000);

}

}需要注意的是:

1)当一个线程正在访问一个对象的synchronized方法,那么其他 线程不能访问该对象的synchronized方法,这个原因很简单,是因为对当一个线程获取了该对象的锁之后,其他线程无法获取该对象的锁,所以无法访问该对象的其他synchronized方法。

2) 当一个线程正在访问对象的synchronized方法,那么其他线程能访问该对象的非synchronized方法。

3) 如果该方法是非static的,则该锁是对象锁。如果方法是static的,则该锁是类锁。对象锁和类锁不互斥。

4) 对于synchronized方法或者synchronized代码块,当出现异常时,JVM会自动释放当前线程占用的锁,因此不会由于异常导致出现死锁现象。

(2) synchronized 代码块

synchronized(synObject){

}

当在某个线程中执行这段代码块,该线程会获取对象synObject的锁,从而使其他线程无法同时访问该代码块。

synObject可是是this,代码获取当前对象的锁,也可以是类中的一个属性,也可以是方法的一个object类型的入参,代表获取该对象的锁。

synchronized代码块使用起来比synchronized方法要灵活得多。如果一个方法中只有一部分代码需要同步,如果此时对整个方法用synchronized进行同步,会影响执行效率。而使用synchronized代码块就可以避免这个问题。

synchronized的缺陷:

当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁,而这里获取锁的线程释放锁只有两种情况:

1) 获取锁的线程执行完了代码块,然后线程释放对应锁的占有。

2) 线程执行发生异常,此时JVM会让线程自动释放锁。

那么如果这个获取锁的线程由于要等待IO或者其他原因(比如调用sleep方法)被阻塞了,但是又没有释放锁,其他线程变只能干巴巴地等待,严重影响程序执行效率。所以就需要有一种机制可以不让等待的线程一直无限地等待下去(比如只等待一定时间或者能够相应中断),通过lock就可以办到。

Lock

1) ReentrantLock:

使用事例:

采用lock,必须主动释放锁,并且在发生异常时,不会自动释放锁。因此一般来说,使用Lock必须在try{}catch{}块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被释放,防止死锁的发生。

Lock lock =new ReentrantLock();

lock.lock();

try{

//执行业务逻辑代码

}catch (Exception e){

}finally {

lock.unlock();

}

2) ReentrantReadWriteLock: 读写锁

readLock用来获取读锁,writeLock用来获取写锁。

读锁可以被多个线程占有。

一个线程已经占用了读锁,则此时其他线程如果要申请写锁,则申请写锁的线程会一直等待释放读锁。

一个线程已经占用了写锁,则其他线程如果申请写锁或者读锁,则申请的线程会一直等待释放写锁。

Lock和synchronized的选择:

总结来说,Lock和synchronized有以下几点不同:

1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;

2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;

3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;

lock是可中断的锁,而synchronized是不可中断锁。lock只能中断等待锁的线程,不能中断正在执行的线程。

4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。

5)Lock可以提高多个线程进行读操作的效率。

在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。

相同:

1) synchronized和lock都是可重入的锁。

参考资料:http://www.cnblogs.com/dolphin0520/p/3920373.html

http://www.cnblogs.com/dolphin0520/p/3923737.html

http://www.cnblogs.com/dolphin0520/p/3923167.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java工作线程 主存 同步机制_Java 并发变成同步机制 的相关文章

  • 做网络赚钱成功的诀窍

    作者 芊蓝小编 日期 2010年07月30日 来源 互联网 1 不要把网络看得多么深奥难懂 它只是你挣钱的一个工具而已 2 问10个人 不如你自己动脑和手真正解析一件事情 3 不要试图掌握网络上的每个知识 谁都不可能学得完 学会跟你工作最相
  • 2012网易校园招聘杭州站笔试

    恩 今天去参加了网易的笔试 题目随后更新 1 长度为M字符串匹配与长度为N的字符串匹配的时间复杂度 我查了查 O M N KMP能做到 这里 http blog csdn net meixr article details 6456896
  • 基于react+springboot校园管理平台的设计与实现

    一 项目介绍 随着信息科学技术的不断发展 很多高校 中学甚至小学都配备了一套管理系统来有效便捷的进行校园管理 学生信息管理 会议管理等 这些系统极大的提高了学校教学的效率与质量 满足了学校对信息管理的要求 但是 在实际应用过程中 这些管理系
  • Python自动化,模糊匹配助力自动答题,准确率高达100%

    前两天的一篇文章给大家分享了利用 Selenium 自动刷课的脚本 时光飞逝 挂脚本刷完时长 又到了要考试的日子 对于这种 无关紧要 的考试 我打算继续使用 聪明 的自动化工具帮我完成考试 爬取题库 想要完成作答 免不了需要题库的支撑 考试
  • 基于opencv与mediapipe手势关键点检测,并使用KNN近邻算法手势识别(石头、剪刀、布)的python代码实现

    本文主要利用opencv读取摄像头的手势画面数据 利用mediapipe库提供的方法将手势图像画面转化为手部21个关节点的坐标值 通过坐标值的数理关系进行任意手势的识别 通过mediapipe拿到21个手势关节点坐标后 对任意手势识别的方法
  • Excel VBA应用:单元格的字母自动大写转换等操作

    Private Sub Worksheet SelectionChange ByVal Target As Range 所有单元格进行字母大写转换 Application EnableEvents False Target VBA UCas
  • hc-05 模块教程2 (两个hc-05连接)

    http www arduino cn thread 21735 1 1 html 最近在做项目需要建立两个hc 05通讯 但网上教程有限和有很多都不是很清楚所以整合了下资料重新做了一份个人认为比较详细的教程和大家一起分享学习 这个教程说明
  • 给github项目贡献代码详细步骤

    本文以 dlink 项目为例 1 fork 第一步是打开 github 上的项目地址 然后点击页面右上角的 fork 按钮 将项目 fork 到自己账号的仓库 记得登录自己的 github 账号 具体看下面图示 这个页面 不需要修改什么参数
  • PHP 常用的设计模式跟使用场景

    策略模式 把类中可能改变的方法用成员属性替换 属性是实现对应方法接口的类 本来直接调用类方法 修改后就是调用成员属性类的方法 这样可以在运行时给类设置不同的成员属性达到动态改变调用的方法 使用 Model 类 持有 Query 类 通过调用
  • Android 项目调用第三方库so动态库

    在Android NDK开发中 可以通过自己编写C C 代码来构建so动态库进行调用之外 还可以把so动态库提供给第三方使用 接下来 我将介绍在新创建的Android 项目 或已存在的Android 项目 中如何调用第三方so动态库 关于如
  • ChatGPT的原理与前端领域实践

    一 ChatGPT 简介 ChatGPT的火爆 ChatGPT作为一个web应用 自22年12月发布 仅仅不到3个月的时间 月活用户就累积到1亿 在此之前 最快记录的保持者也需要9个月才达到月活1亿 ChatGPT的反爬 https cha
  • 02-react组件基础-函数组件-类组件(有状态和无状态组件)-事件处理(this指向)-setState修改状态-表单处理(受控组件和非受控组件)-案例

    学习目标 能够使用函数创建组件 函数组件 能够掌握class语法 extends继承 能够使用class创建组件 类组件 能够给React元素绑定事件 能够使用state与setState 能够处理事件中this的指向问题 能够使用受控组件
  • mysql,oracle,sqlserver之表备份

    mysql表备份 1 只复制表结构到新表 只有结构无数据 create table 新表 select from 旧表 where1 2 或create table 新表 like 旧表 此两种方法的区别 使用第一条语句 备份的新表并没有旧
  • C++之共享智能指针shared_ptr的实现

    目录 概念 使用标准库共享智能指针 共享智能指针底层实现 概念 共享指针是可以 由多个栈上智能指针对象 同时托管同一堆上资源的 因为shared ptr的内部实现引用计数来管理有多少智能指针指向了这块堆上资源 当一个共享智能指针出栈时 引用
  • 人脸建模1

    宝宝 把眼睛球体控制器和簇点的translate属性关联之后 选中眼睛一圈隔一个选一个面 给上nhair毛囊 删除结算器等 只留图中鼠标所在位置 毛囊分别对对应位置控制器父子约束 所有控制器做好之后一定要冻结 舌头控制器前面的组p给后面的盒
  • 二、C++语言进阶:动态库与静态库之函数篇

    2 动态库与静态库之函数篇 作用 分离编译 代码重用 分类 分类 作用 后缀 静态库 一个或多个 o目标文件归档在一个文件中 a 共享库 没有main函数的可执行文件 so 动态加载库 没有main函数的可执行文件 接口复合API so 2
  • 让树叶摇动起来

    Shader XW Tree TreeLeaf Simple Properties Color Main Color Color 1 1 1 1 clipAlpha clip Alpha Range 0 1 0 5 MainTex Base
  • Nginx 服务器

    简介 Nginx 是一款HTTP和反向代理服务器 它的内存占用少 能够支持高达五万个并发连接响应 其主要有三个功能 反向代理 负载均衡 反向代理 正向代理 就相当于 VPN 当你想要访问一个服务器但是由于某种原因不能直接访问时 可以去访问一
  • 如何使用 Vagrant 命令行工具创建和管理虚拟机

    创建和管理虚拟机曾经是一个乏味且耗时的过程 在不同的服务器上复制虚拟机也可能具有挑战性 如果必须复制多个虚拟机 情况会变得更加困难 但后来 Vagrant 出现了 它是一种通常与2 类虚拟机管理程序配合使用的命令行或 shell 工具 你可

随机推荐

  • QT从入门到实战x篇_06_信号和槽2:自定义信号和槽函数的创建及使用

    接上文 QT从入门到实战x篇 xx 信号和槽1 Qt中自带的信号和槽函数的使用方法本文主要介绍如何根据自身的功能需要 创建和使用自定义信号及槽函数 先写出一个功能需求 下课后 老师触发信号 饿了 学生响应信号 请客吃饭 1 建立老师类和学生
  • jquery ztree实现下拉树形框,json数据

    公司最近的项目需要用到树形下拉框 在网上找了挺多源码 最后还是采用了zTree来实现 因为代码的移植性比较高 而且数据的获取比较容易 废话不多说 直接上代码 index jsp
  • 轻量应用服务器腾讯云和阿里云哪家更好?

    轻量应用服务器阿里云和腾讯云哪个好 云服务器吧认为腾讯云轻量应用服务器还不错 腾讯云轻量服务器30元起 配置可选2核2G3M 2核2G4M 2核4G5M 4核8G12M 8核16G18M和16核32G28M 阿里云轻量应用服务器配置仅可以选
  • C语言函数大全-- w 开头的函数(1)

    w 开头的函数 1 1 wcscat 1 1 函数说明 1 2 演示示例 1 3 运行结果 2 wcschr 2 1 函数说明 2 2 演示示例 2 3 运行结果 3 wcscmp 3 1 函数说明 3 2 演示示例 3 3 运行结果 4
  • AHB接口总线仲裁1主多从细节。关于hready in和hready out信号的理解

    所有slaver 只要有1个hready out等于0 表示slaver没有准备好执行此拍操作 这时 所有slaver都不能执行此拍操作 以防止1主多从的AHB接口协议问题 所有slaver的hreadyout 需要与之后 提供给所有sla
  • linux下c++操作MySQL

    第一步 先在Linux中安装MySQL 第二步 在安装连接器 中端命令 sudo apt get install libmysqlclient dev 第三步写一个操作MySQL的c 代码保存退出 include
  • allegro如何对差分对单根网络进行等长调节

    选中要调整的差分线 再点击左栏的快捷按钮 此时options会弹出相关的调整s参数 设置好差分线参数 鼠标放在刚才选中的线上拉出一个方框 方框内就会显示线的形状变化 再次点击鼠标后 就会把线绘制成曲线形状 蛇形走线 在这里注意 如果调整走线
  • Redis缓存穿透, 击穿, 雪崩

    缓存穿透 缓存穿透是指用户想要查询一个数据 发现redis内存中没有 也就是没有缓存命中 于是向持久层数据库查询 发现也没有 于是本次查询失败 当用户很多的时候 缓存中都没有 于是都去请求持久层数据库 这会给持久层数据库造成很大压力 这就是
  • kafka 不支持读写分离的原因

    前段时间在看 kafka 相关内容 发现 kafka 所有的 读写流量都在主 partition 上 从 partition 只负责备份数据 那么为什么 kafka 从 partition 不跟其他中间件一样承接读流量 读写分离的初衷 读写
  • LoadRunner11 脚本关联操作-(学习中)

    一 首先了解关联的定义 服务器返回给客户端的是一些动态变化的值 客户端使用动态变化的值去访问服务器的时候 不能把这些值写死在脚本里面 而应该存放在一个变量里面 实时去获取服务器返回的动态值 简而言之 就是将录制脚本的静态值 再转换成动态值
  • 2021-1-30Linux学习纪要

    压缩和解压类 gzip gunzip gzip 用与压缩文件 gunzip 用于解压缩文件 特点把文件压缩之后原来的文件就没有了 同样的解压之后 压缩文件也没有了 zip 选项 xxx zip 将要压缩的内容 功能描述 压缩文件和目录的命令
  • 百川智能发布开源中英文大模型;GitHub调查显示92%的程序员使用AI编码工具;第一季度中国云服务支出增长6%丨每日大事件...

    数据智能产业创新服务媒体 聚焦数智 改变商业 企业动态 百川智能发布开源中英文大模型 6月15日 百川智能公司推出了70亿参数量的中英文预训练大模型 baichuan 7B baichuan 7B在C Eval AGIEval和Gaokao
  • 4.决策树

    决策树 一 决策树概述 训练阶段 根据训练数据构造决策树模型 在测试阶段 对数据进行分类 决策树重要的三个阶段 1 特征的选择 2 决策树的生成 3 决策树剪枝 决策树内部节点表示特征或者属性 叶节点表示类别 特征的选择 根据信息增益 ID
  • totimestamp mysql_mysql多个TimeStamp设置

    timestamp设置默认值是Default CURRENT TIMESTAMP timestamp设置随着表变化而自动更新是ON UPDATE CURRENT TIMESTAMP 但是由于 一个表中至多只能有一个字段设置CURRENT T
  • 使用websocket模拟一下发送和接收消息

    好的 下面是使用 WebSocket 模拟发送和接收消息的一些指导思路 在客户端和服务端之间建立 WebSocket 连接 客户端可以使用 JavaScript 的 WebSocket 对象来建立连接 服务端可以使用支持 WebSocket
  • 图像识别小车(PCB设计)——电赛学习笔记(4)

    学习来源 B站唐老师讲电赛 PCB设计极速入门 立创EDA ALTIUM DESIGNER 10 0PCB设计极速入门 立创EDA ALTIUM DESIGNER 10 0 哔哩哔哩 bilibili 一 设计过程 使用嘉立创EDA加Alt
  • 【初探DETR】UP-DETR 复现

    项目链接 https github com dddzg up detr 论文 https arxiv org abs 2011 09094 UP DETR 遵循两个步骤 预训练和微调 展示了在 ImageNet 上预训练的模型 然后在 CO
  • MOS管的使用方法

    转载自http blog csdn net qingwufeiyang12346 article details 48385773 http user qzone qq com 2756567163 1 三个极的判定 栅极 G 中间抽头 源
  • java 分布式日志_打造分布式日志收集系统

    前言 系统一大 就会拆分成多个独立的进程 比如web wcf web api等 也就成了分布式系统 要看一个请求怎么从头到尾走的 就有些困难了 要是进行DEBUG 跟踪 就更加麻烦了 困难程度要视进程多少而定 越多越复杂 分布式日志收集系统
  • Java工作线程 主存 同步机制_Java 并发变成同步机制

    并发编程的演进 批处理 多进程 多线程 在多线程变成中 由于多个线程共享进程的变量 有可能出现同时访问一个资源的情况 因此需要使用同步机制 java的内存模型 Java内存模型规定所有的变量都存在主存当中 每个线程都有自己的工作内存 线程对