知识大全 Java线程安全总结
Posted 知
篇首语:出门莫恨无人随,书中车马多如簇。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 Java线程安全总结相关的知识,希望对你有一定的参考价值。
Java线程安全总结 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
最近想将java基础的一些东西都整理整理 写下来 这是对知识的总结 也是一种乐趣 已经拟好了提纲 大概分为这几个主题 java线程安全 java垃圾收集 java并发包详细介绍 java profile和jvm性能调优 慢慢写吧 本人jameswxx原创文章 转载请注明出处 我费了很多心血 多谢了 关于java线程安全 网上有很多资料 我只想从自己的角度总结对这方面的考虑 有时候写东西是很痛苦的 知道一些东西 但想用文字说清楚 却不是那么容易 我认为要认识java线程安全 必须了解两个主要的点 java的内存模型 java的线程同步机制 特别是内存模型 java的线程同步机制很大程度上都是基于内存模型而设定的 后面我还会写java并发包的文章 详细总结如何利用java并发包编写高效安全的多线程并发程序 暂时写得比较仓促 后面会慢慢补充完善
浅谈java内存模型
不同的平台 内存模型是不一样的 但是jvm的内存模型规范是统一的 其实java的多线程并发问题最终都会反映在java的内存模型上 所谓线程安全无非是要控制多个线程对某个资源的有序访问或修改 总结java的内存模型 要解决两个主要的问题 可见性和有序性 我们都知道计算机有高速缓存的存在 处理器并不是每次处理数据都是取内存的 JVM定义了自己的内存模型 屏蔽了底层平台内存管理细节 对于java开发人员 要清楚在jvm内存模型的基础上 如果解决多线程的可见性和有序性
那么 何谓可见性?多个线程之间是不能互相传递数据通信的 它们之间的沟通只能通过共享变量来进行 Java内存模型(JMM)规定了jvm有主内存 主内存是多个线程共享的 当new一个对象的时候 也是被分配在主内存中 每个线程都有自己的工作内存 工作内存存储了主存的某些对象的副本 当然线程的工作内存大小是有限制的 当线程操作某个对象时 执行顺序如下
( )从主存复制变量到当前工作内存(read and load)
( )执行代码 改变共享变量值(use and assign)
( )用工作内存数据刷新主存相关内容(store and write)
JVM规范定义了线程对主存的操作指令 read load use assign store write 当一个共享变量在多个线程的工作内存中都有副本时 如果一个线程修改了这个共享变量 那么其他线程应该能够看到这个被修改后的值 这就是多线程的可见性问题
那么 什么是有序性呢?线程在引用变量时不能直接从主内存中引用 如果线程工作内存中没有该变量 则会从主内存中拷贝一个副本到工作内存中 这个过程为read load 完成后线程会引用该副本 当同一线程再度引用该字段时 有可能重新从主存中获取变量副本(read load use) 也有可能直接引用原来的副本(use) 也就是说 read load use顺序可以由JVM实现系统决定
线程不能直接为主存中中字段赋值 它会将值指定给工作内存中的变量副本(assign) 完成后这个变量副本会同步到主存储区(store write) 至于何时同步过去 根据JVM实现系统决定 有该字段 则会从主内存中将该字段赋值到工作内存中 这个过程为read load 完成后线程会引用该变量副本 当同一线程多次重复对字段赋值时 比如
Java代码
for(int i= i< i++)
a++ 线程有可能只对工作内存中的副本进行赋值 只到最后一次赋值后才同步到主存储区 所以assign store weite顺序可以由JVM实现系统决定 假设有一个共享变量x 线程a执行x=x+ 从上面的描述中可以知道x=x+ 并不是一个原子操作 它的执行过程如下
从主存中读取变量x副本到工作内存 给x加 将x加 后的值写回主 存
如果另外一个线程b执行x=x 执行过程如下
从主存中读取变量x副本到工作内存 给x减 将x减 后的值写回主存
那么显然 最终的x的值是不可靠的 假设x现在为 线程a加 线程b减 从表面上看 似乎最终x还是为 但是多线程情况下会有这种情况发生
线程a从主存读取x副本到工作内存 工作内存中x值为 线程b从主存读取x副本到工作内存 工作内存中x值为 线程a将工作内存中x加 工作内存中x值为 线程a将x提交主存中 主存中x为 线程b将工作内存中x值减 工作内存中x值为 线程b将x提交到中主存中 主存中x为
同样 x有可能为 如果x是一个银行账户 线程a存款 线程b扣款 显然这样是有严重问题的 要解决这个问题 必须保证线程a和线程b是有序执行的 并且每个线程执行的加 或减 是一个原子操作 看看下面代码
Java代码
public class Account
private int balance
public Account(int balance) this balance = balance
public int getBalance() return balance
public void add(int num) balance = balance + num
public void withdraw(int num) balance = balance num
public static void main(String[] args) throws InterruptedException Account account = new Account( ) Thread a = new Thread(new AddThread(account ) add ) Thread b = new Thread(new WithdrawThread(account ) withdraw ) a start() b start() a join() b join() System out println(account getBalance())
static class AddThread implements Runnable Account account int amount
public AddThread(Account account int amount) this account = account this amount = amount
public void run() for (int i = i < i++) account add(amount)
static class WithdrawThread implements Runnable Account account int amount
public WithdrawThread(Account account int amount) this account = account this amount = amount
cha138/Article/program/Java/hx/201311/26952相关参考
Java多线程操作相关问题总结 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  
Java线程安全和非线程安全 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! ArrayList和
Java容器类的线程安全 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! Java容器类的关系图
java中原子操作是线程安全的论调经常被提到根据定义原子操作是不会被打断地的操作因此被认为是线程安全的实际上有一些原子操作不一定是线程安全的 这个问题出现的原因是尽量减少在代码中同步关键字同
Java理论与实践:描绘线程安全性[2] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 线程安全
Java理论与实践:描绘线程安全性[1] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 定义线程
Java系统线程组如何才能安全组建 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 我们在使用Ja
基于Java2运行时安全模型的线程协作 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 在Java
JavaSwing开发中的线程安全 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! SwingAP
Java开发中的线程安全选择与Swing 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! Swin