并发编程之美,带你深入理解java多线程原理
1.什么是多线程?
多线程是为了使得多个线程并行的工作以完成多项任务,以提高系统的效率。线程是在同一时间需要完成多项任务的时候被实现的。
2.了解多线程

了解多线程之前我们先搞清楚几个重要的概念!
如上图所示:对我们的项目有一个主内存,这个主内存里面存放了我们的共享变量、方法区、堆中的对象等。
3.线程的工作过程
每当我们开启一个线程的时候,线程会为我们开辟一块工作内存,将主内存中的共享变量复制一个副本存入工作内存中,并协调方法区生成栈针,以及对堆的引用(指针)。
如果在执行过程中线程对工作内存中的共享变量进行的修改操作,此时会向主内存回写我们修改的变量。
4.多线程带来的问题
我们模拟这样一个场景:
有十个用户同时购票,但是系统中只剩下了8张票,当每个用户同时开启自己的线程,将主内存中8张票复制到工作内存中,在方法中,会判断票数是否满足要求,此时,十个线程都判断满足,都要对票数进行操作。
当用户一操作后,票数=8-1=7,将数据回写至主内存。
用户二操作后,用户二的本地内存中票数为8,则修改后票数=8-1=7,继续回写至主内存,
以此下去,在我们假设十个用户同时开启线程的情况下最后主内存中的票数肯定是7,而且十个用户均出票成功,出现了超卖的情况,这在现实场景是很危险的事!
5.多线程的特性
有序性:程序执行的顺序按照代码的先后顺序执行。
可见性:当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
若两个线程在不同的cpu,那么线程1改变了i的值还没刷新到主存,线程2又使用了i,那么这个i值肯定还是之前的,线程1对变量的修改线程没看到这就是可见性问题。
原子性:即一个操作或者多个操作要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。
在程序编译到执行的过程中,程序会经过多次重排序,源代码->编译器优化重排序->指令级并行重排序->内存系统重排序->最终执行的指令序列,
也就是说我们编写的代码,经过这一连串的重排序后,代码很可能就和我们写的顺序不一致了,但是我们的操作系统等会保证我们
最终执行的指令序列与我们的源代码的结果保持一致,我们的操作系统是可以保证单线程的有序性的。
6.怎么解决多线程并发带来的问题?
什么时候需要使用多线程?
竞态条件:检查后执行是否满足决定下一步。
方法一:加锁
1.监视器锁synchronized,它确保了每个线程是隔离的,而且只有当一个线程执行进入带有synchronized的方法中时加锁,
当该线程为结束此方法解锁时,其它线程将挂起,直到该线程解锁后其它线程才能继续执行下去。它能够保证上述三大特性:有序性、可见性、原子性。
JMM定义内存访问规范,实现有序性、可见性、原子性,共八大规则,大家可以上网了解JMM详细规则信息。
同步机制:
监视器锁synchronized
显示锁ReentrantLock、ReadWriteLock
原子变量AtomicInteger、AtomicLong、AtomicBoolean
Volatile
问题:遇到同步问题如何选择具体的实现方式?
监视器锁在jdk1.5以后,性能得到了很大的提升,并且在java版本更新中一直在被优化,而且synchronized锁可以自动实现加锁与解锁。
显示锁需要我们手动解锁、加锁,容易失误导致死锁。
在考虑性能时,推荐使用监视器锁,当考虑功能时,推荐使用显示锁,显示锁拥有更多自定义的选择。
方法二:线程封闭
什么是线程封闭?
当访问共享的可变数据时,通常需要同步,一种避免同步的方式就是不共享数据,如果仅在单线程内访问数据,就不需要同步,这种技术称为线程封闭。
如果使用线程封闭:1.栈封闭:线程为跳用方法生成栈针时局部变量就使用了线程封闭。
2.ThreadLocal --> 只有当前线程能使用。
方法三:不可变对象一定是线程安全的。
最佳方案:使用线程安全的对象是实现线程安全的。 java.util.concurrent包下的类。
并发编程之美,带你深入理解java多线程原理的更多相关文章
- Java并发编程之set集合的线程安全类你知道吗
Java并发编程之-set集合的线程安全类 Java中set集合怎么保证线程安全,这种方式你知道吗? 在Java中set集合是 本篇是<凯哥(凯哥Java:kagejava)并发编程学习> ...
- Java并发编程之CAS
CAS(Compare and swap)比较和替换是设计并发算法时用到的一种技术.简单来说,比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替 ...
- 并发编程之wait()、notify()
前面的并发编程之volatile中我们用程序模拟了一个场景:在main方法中开启两个线程,其中一个线程t1往list里循环添加元素,另一个线程t2监听list中的size,当size等于5时,t2线程 ...
- python并发编程之multiprocessing进程(二)
python的multiprocessing模块是用来创建多进程的,下面对multiprocessing总结一下使用记录. 系列文章 python并发编程之threading线程(一) python并 ...
- 2017“编程之美”终章:AI之战勇者为王
编者按:8月15日,第六届微软“编程之美”挑战赛在选手的火热比拼中圆满落下帷幕.“编程之美”挑战赛是由微软主办,面向高校学生开展的大型编程比赛.自2012年起,微软每年都在革新比赛命题.紧跟时代潮流, ...
- Python核心技术与实战——十七|Python并发编程之Futures
不论是哪一种语言,并发编程都是一项非常重要的技巧.比如我们上一章用的爬虫,就被广泛用在工业的各个领域.我们每天在各个网站.App上获取的新闻信息,很大一部分都是通过并发编程版本的爬虫获得的. 正确并合 ...
- Java并发编程之CAS第一篇-什么是CAS
Java并发编程之CAS第一篇-什么是CAS 通过前面几篇的学习,我们对并发编程两个高频知识点了解了其中的一个—volatitl.从这一篇文章开始,我们将要学习另一个知识点—CAS.本篇是<凯哥 ...
- Java并发编程之CAS第三篇-CAS的缺点及解决办法
Java并发编程之CAS第三篇-CAS的缺点 通过前两篇的文章介绍,我们知道了CAS是什么以及查看源码了解CAS原理.那么在多线程并发环境中,的缺点是什么呢?这篇文章我们就来讨论讨论 本篇是<凯 ...
- 并发编程之ThreadLocal
并发编程之ThreadLocal 前言 当多线程访问共享可变数据时,涉及到线程间同步的问题,并不是所有时候,都要用到共享数据,所以就需要线程封闭出场了. 数据都被封闭在各自的线程之中,就不需要同步,这 ...
随机推荐
- WMWaire使用FreeNAS硬盘挂载、Raid0
FreeNAS硬盘挂载.Raid0 发表于2012 年 03 月 28 日由admin 创建成功,FreeBSD的Hardware显示状态 今天,我们将在VMware工具的帮助下,学习“FreeNAS ...
- 简洁的导出 datatable到excel,不用组件
简洁的导出 datatable到excel var lines = new List<string>(); string[] columnNames = dataTable.Columns ...
- Win8Metro(C#)数字图像处理--2.14Prewitt 边缘检测
原文:Win8Metro(C#)数字图像处理--2.14Prewitt 边缘检测 [函数名称] 图像Prewitt边缘检测函数PrewittEdgeProcess(WriteableBitmap ...
- Win8MetroC#数字图像处理--2.2图像二值化函数
原文:Win8MetroC#数字图像处理--2.2图像二值化函数 [函数代码] /// <summary> /// Binary process. /// </summary> ...
- Resources.resx 未将对象引用设置到对象的实例
原文:解决使用DevExpress开发错误:未将对象引用设置到对象的实例 在使用DevExpress是总是会出现一些状况.这次同事在他的机器上调试完毕的代码发过来,却出现“未将对象引用设置到对象的实例 ...
- ARTS 12.10 - 12.14
从陈皓博主的专栏里学到一个概念,争取可以坚持下去: 我在我的读者群中推荐出 ARTS 的任务,每个人每周一个 Algorithm,Review 一篇英文文章,总结一个工作中的技术 Tip,以及 Sha ...
- mysql自动化安装脚本(二进制安装)
为了日后安装数据库方便,遂写了一个自动安装MySQL的脚本: 测试可以安装mariadb和MySQL-5.7.X 安装前配置好对应的my.cnf文件放在/tmp路径下 将启动脚本mysql3306放在 ...
- CoolFormat(Qt Creator也可管理VC的Project)
http://download.csdn.net/download/akof1314/8457593 https://github.com/akof1314/CoolFormat http://dow ...
- 从Qt5开始只剩下setCodecForLocale这一个了,只是影响Qt对toLocal8Bit相关函数的编码方式(在源码里写非英文,官方推荐“\xE4\xBD...”这种)good
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); QTextCodec::setCodecFo ...
- Design Thinking Workshop @ Agile Tour 2013 Shanghai
设计思维工作坊 上周日在2013年敏捷之旅上海站,引导分享了一个设计思维的工作坊.这个工作坊持续了3个小时.来篇流水账分享给大家. 我们的设计挑战是什么呢?左思右想,在准备设计挑战题目的时候纠结了好久 ...