Java Concurrency 基础知识

1.线程安全 
a.无状态的类是线程安全的 
b.所有状态都具有原子性的类是线程安全的 
原子性:即对该类的操作是不被打断的,即使在多线程的环境下 
如果一个类只有单个状态,推荐使用jdk中的java.util.concurrent.atomic包AtomicBoolean 
AtomicInteger 
AtomicIntegerArray 
AtomicIntegerFieldUpdater 
AtomicLong 
AtomicLongArray 
AtomicLongFieldUpdater 
AtomicMarkableReference 
AtomicReference 
AtomicReferenceArray 
AtomicReferenceFieldUpdater 
AtomicStampedReference 
这些类作为状态都具有原子性 
2.Synchronized 
a.如果一个方法用Synchronized关键字修饰,则调用该方法所用的锁,为调用方法的对象的固有锁(如反射),如果同时带有Static关键字修饰,则使用的锁为该方法所在的类的固有锁。 
固有锁:每个对象都隐性地带有一个锁,该锁为重入锁(重入锁将在后文介绍),用于synchronized关键字

3.重入锁 
关于重入锁的解释用书中英文的解释会更准确:But because intrinsic locks are reentrant, if a thread tries to acquire a lock that it already holds, the request succeeds.

可能看完上面的还是有点难理解 
举一个书中的例子: 
看以下代码 
 
假设不是可重入锁,那会出现一个什么现象? 
调用super.doSomething()时发现该方法被锁住了,然后等待,但等待的锁自己正持有着,也就变成了死锁

重入锁的实现: 
重入锁是通过一个count和记录owner--一个持有该锁的Thread来实现的。当count值为0,认为这个锁当前没被任何线程持有。当 一个线程持有了该锁了,jvm就会把owner置为该线程,并把count置为1,如果同样锁线程再次请求该锁,那jvm就会把count+1,如果线程 退出同步块,则count-1,当count为0时,锁就释放了。

4.线程状态的锁操作 
对于每一个涉及到多个变量的不变量,所有涉及到的变量都应该用同一个锁来进行同步 
怎么理解呢? 
看例子: 
 
在vector中,每个方法都是用synchronized修饰的,但在上面的使用中--如果两个线程先后进入该语句块,再轮流执行 vector.contain(element),显然还是会添加两次同样的element到vector中,所以还是不能保证vector的原子性

5.程序中的代码是可能被打乱的 
如果没有进行同步,编译器,进程,和运行环境将有可能会打乱运行的顺序。 
如文中所举例子: 
 
将有可能出现这样的状况:输出结果为0. 
这是因为执行的顺序被打乱了

6.64位数据的读或写是非原子性的 
一般的数据类型,如int,执行 
int a = 1; 
int b = a; 
这些操作都是原子操作,但是像long,double就不是了 
jvm是允许把64位数据的读和写分开两次操作的,每次操作32位。 
因此,有些项目,我们对某些数据的实时性不会太在意,就不会定义该变量为原子变量,但如果是long或者double类型,就要小心了。很有可能某用户在读取的时候读到的是前一个数据的前32位,和后一个数据的后32位

7.volatile关键字 
当一个变量用volatile声明了,编译器会放一个notice到该变量的共享区,然后当执行的时候,就不会对这个变量在程序中的执行顺序进行 修改。并且volatile不会缓存在寄存器中,也不会缓存在别的进程中,因此,读volatile修饰的变量时总能返回一个最新更新的值。

使用锁能同时保证变量的可见性和原子性,但volatile只能保证其可见性。

什么时候不适合使用volatile? 
举一个经典的例子:i++操作,在并发环境下volatile是不能保证其正确性的

什么时候可以用volatile? 
* 该变量的值不依赖该变量当前的值,像i++,或者你能保证该变量的更新只在单线程的环境下出现 
* 该变量不和其他的变量一起包含在一个不变量中,如上文的vector 
* 由于其他的原因,该变量不需要使用锁

时间: 2024-08-28 11:16:12

Java Concurrency 基础知识的相关文章

黑马程序员——Java集合基础知识之Map

Map概念 要同时存储两个元素Key和Value,他们之间有映射关系,每个键不能重复,每个键只能映射到一个值. 当数据之间存在映射关系的时候,考虑使用Map集合. Map常用方法 如果添加的键原来有值,后添加的值会覆盖前面的值,并返回之前的值.put会返回来先添加的值,后添加的值会覆盖原有的值. Map tm =new TreeMap(); tm.put (key, value);//MAP没有add tm.remove (key) ;//去除一个key和对应的value,若不存在key返回nu

黑马程序员——Java集合基础知识之Collection

集合基础知识--Collection Java中集合框架由常用的Collection接口和Map接口组成,而Collection接口又有两个子接口,是List接口和Set接口,常用的集合框架由这三个类组成. List接口的功能方法 List的使用最为简单,创建集合,通过add方法添加元素,get方法获取元素,通过迭代器获取元素.List接口存放的数据无序的,添加速度快,但是查询速度慢,因为查询的时候必须遍历,每次都重头开始,效率较低.常用实现类有ArrayList,LinkedList. Lis

什么才是java的基础知识?

近日里,很多人邀请我回答各种j2ee开发的初级问题,我无一都强调java初学者要先扎实自己的基础知识,那什么才是java的基础知识?又怎么样才算掌握了java的基础知识呢?这个问题还真值得仔细思考. 我做j2ee开发已经超过十载,作为过来人,心路历程估计和大家差不多.编码的前几年,很长一段时间觉得java简单,开发实现各种功能都很轻松,代码写起来根本不费劲(主要是因为写的代码都是一些功能业务逻辑).但同时自己心里明白,自己其实没有什么水平,自己这3,4年以来学懂的东西就那么多,其他人几个月就可以

java多线程基础知识

1.ThrTest.java 继承Thread类方式 public class ThrTest extends Thread { private String name; public ThrTest() { } public ThrTest(String name) { this.name = name; } public void run() { for (int i = 0; i < 5; i++) { System.out.println(name + "运行 " + i

黑马程序员——java多线程基础知识1

多线程 进程是一个正在执行的程序. cpu在同时执行这些程序,其实是跳跃式的,做快速的切换,时间很短.一个进程可能存在多条路径.迅雷的多路径.每一个进行执行都有一个执行顺序,该顺序是一个执行路径,或这叫一个控制单元.每一个进程至少有一个线程,线程就是进程中的一个独立的控制单元,线程控制进程的执行.jvm启动的时候会有一个进程就叫做java,exe,该进程中至少有一个线程在控制Java程序的执行 ,而且该线程的执行代码在 主函数中.该线程称为主线程.虚拟机至少也有两个线程,一个主线程执行,另一个负

黑马程序员——Java多线程基础知识2

多线程协同 线程间的通讯:我们对资源的操作动作不同,比如说两个卡车一个拉煤一个装煤.但是他们共享了一个资源. 怎么样把这个资源拿出来?怎样把车装满?这个资源当然是一个类,他里面的组成元素就是对象!!现在我们就要有操作对象的思想了,我用对象把这车装满,现在一车装一个对象. 等待唤醒机制: 用的不是sleep是wait.flag标记,这是两人沟通的方式.其实每个标记就要做一次等待或者notify,判断wait,改值notify.线程池.notify唤醒里面的线程,按顺序唤醒.wait和notify必

Java 接口基础知识

一.Java接口基础知识 1, Java语言不支持一个类有多个直接的父类(多继承),但可以实现(implements)多个接口,间接的实现了多继承. 2, 与Java接口相关的设计模式: 1, 定制服务模式 设计精粒度的接口,每个Java接口代表相关的一组服务,通过继承来创建复合接口 2, 适配器模式 当每个系统之间接口不匹配时,用适配器来转换接口 3, 默认适配器模式 为接口提供简单的默认实现 4, 代理模式 为Java接口的实现类创建代理类,使用者通过代理来获得实现类的服务 5, 标识类型模

Java Web基础知识之Filter:过滤一切你不想看到的事情

不要相信客户端, 所以做后端的人都应该铭记的事情.因为前端传过来的数据并不总是合法和有效的,所以后端是对访问资源的最后一道保护伞.之前我们在Spring中说到过AOP编程,AOP基础知识,它就可以在执行我们的方法之前进行一些预处理和验证来保护后端的资源.不难想到她的实现方式和本篇要说的过滤器的实现原理应该是相同的,都是通过Java的动态代理实现的(自己的理解). 在Java Web的开发中,过滤器用于拦截请求,并对ServletRequest对象进行处理,我们可以想到的,它可以用来验证权限.加密

初识Java及基础知识

java不仅仅是一种程序设计语言,他还是一个完整的平台,有一个庞大的代码库.首先你要做的,可能需要下载 jdk 包,下载和安装,自行百度. 下载完 jdk 之后,JDK目录树如下:  目录结构 描述 bin 编译器和工具 demo 演示 docs HTML格式的类库文档(解压 2sdkversion-doc.zip 之后j) include 用于编译本地方法的文件 jre Java 运行环境 lib 类库文件 src 类库源文件 java 中基本程序设计会用的基础知识:数据类型.变量.运算符.字