java 多线程线程安全
时间:2022-07-22
本文章向大家介绍java 多线程线程安全,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
在多线程中使用共享资源,对共享资源的操作不是原子性,就会导致数据不一致的情况 例如 : index ++ 操作 index ++ 实际上相当于 1. index + 1 2. 将结果赋值 index
- 数据漏过
主要是由于线程1修改后index值已改变未输出前,cpu将权利交给线程2,线程2继续累加并输出
2.数据重复
主要是由于线程1执行到index +1但是还没赋值index,cpu就将执行权交给线程2
3.超过最大值
当index=499 时线程1和线程2都看到满足条件,线程1将index增加到500后,线程2恢复执行变为501
synchronized
synchronized 实现同步
- 提供一种锁机制,确保共享变量互斥访问
- synchronize 关键字包括 monitor enter 和 monitor exit 两个JVM,保证任何时候线程执行到monitor enter成功之前都必须从主内存中获取数据,而不是缓存,在monitor exit 运行成功后,共享变量被更新的值必须刷入主内存中
- synchronied 严格遵守 java happens-before 规则,一个monitor exit指令之前,必定要有一个monitor enter
- Monitorenter
每一个对象都与一个monitor相关联,一个monitor的lock的锁只能被一个线程在同一时间获得.
如果monitor的计数器为0,则意味着monitor的lock还没有被获得,某个线程获得之后计数器加1
如果一个monitor的所有权的线程重入,则会导致moniter的计数器再次累加
如果monitor已经被其他线程所拥有,则其他线程再尝试获取所有权时,被陷入阻塞状态,直到monitor计数器变为0,才能再次获取
- Monitor exit
释放monitor所有权就是将计数器减一,前提是必须拥有所有权
注意: 1. monitor关联对象不能为空 2. synchronized的作用域不要太大,越大效率越低
3.不同的monitor不要使用相同的锁, 4. 多个锁的交叉导致死锁
public static class Task implements Runnable{
//这里如果初始化多个任务将使用同一个锁.
private final Object MUTEX = new Object();
publiv void run(){
synchronized(MUTEX){
}
}
}
This Monitor 和 Class Monitor
在 同一个类中的两个方法上加synchronized,导致两个方法共用同一个 this monitor锁,
同样的在同一个类中的两个静态的方法,分别使用 synchronized 进行同步,两个方法被加同样的class 锁
死锁的原因
- 交叉锁导致死锁
A 持有 R1 等待 R2 , B 持有 R2 等待 R1
2.内存不足
共30M内存,A持有 10 ,B 持有 20 , 都在等待资源
3.一问一答数据交换
4.死循环造成的锁.
5.数据库和文件锁
- C++服务器开发之笔记三
- 分布式服务注册和发现consul 简要介绍
- ZooKeeper 笔记(3) 实战应用之【统一配置管理】
- 3D游戏开发之在UE4中创建非玩家角色(NPC)
- VMware Fusion DHCP方式下如何指定虚拟机IP地址
- Visual Studio 2015正式发布
- 科技巨头纷纷入局 医疗人工智能需要奋起直追?
- Windows PowerShell 工具
- 游戏开发之在UE4中编写C++代码控制角色
- Visual Studio 64位应用程序编译
- Windows 7 上安装Visual Studio 2015 失败解决方案
- Silverlight调用本机exe程序
- 游戏开发之UE4添加角色到场景中
- 人工智能取代人类?高通副总裁这样说
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Linux上也有10个流行的Windows应用程序
- (译)SDL编程入门(14)动画精灵和VSync
- 在Ubuntu Linux上安装和使用Git和GitHub
- 10个好用的 HTML5 特性
- Linux下升级python和安装pip的详解
- Linux中使用top命令的技巧
- Linux中查找工具的友好替代方案
- 使用命令行检测Ubuntu版本方法
- 一键实现 PowerBI 度量值批量重命名
- Ubuntu E: 无法获得锁 /var/lib/dpkg/lock-frontend – open (11: 资源暂时不可用)
- Ubuntu 18.04 安装MySQL时未提示输入密码的问题及解决方法
- ubuntu中修改grub的启动时间生成
- linux7下虚拟主机的三种实现方式
- 详解CentOS7下PostgreSQL 11的安装和配置教程
- CentOS下安装Memcached和PHP Memcached扩展