并发编程----2.并发编程其他基础知识

并发编程----2.并发编程其他基础知识

2.1 什么是多线程并发编程

并发和并行的概念:并发指的是在单核cpu下,同一时间段内多线程运行。并行指的是多核cpu在同一时间点内多线程运行。

2.2 为什么是多线程并发编程

虽然多核cpu的到来,减少了cpu切换上下文的开销,但是处理海量数据和请求的要求,这些都对于高并发编程有着急切的需求

2.3 Java中的线程安全问题

多个线程访问同一共享变量却没有进行同步操作,导致脏数据的出现

2.4 java中共享变量的内存可见性问题

	(1)cpu内存模型:线程拥有各自的私有内存,所有cpu共享的二级缓存,主内存
	
	(2)线程操作共享变量:线程将查看私有内存是否存在相关变量,如果存在,刷新后复制到主存中,如果二级缓存中存在复制到
	 私有内存,刷新后复制到主存中。如果不存在,复制主存中变量到私有内存中,刷新复制到二级缓存,刷新到主内存。

2.5 java中synchronized关键字

	(1)synchronized 关键字介绍
		
			1. synchronized块是java提供的一种原子内置锁,也可以看做同步锁,这些java内置使用者看不到的内置锁成为内
			   部锁,也叫监视器锁。
			2. 当线程进入synchronized块中便会获得内置锁,其他线程进入就会被挂起,在获得锁的线程顺利执行完,或者使用
		   	   wait放弃当前的锁他会释放该锁。
			3. synchronized也是一种排他锁,当一个线程获得该锁时,其他线程要获取会被阻塞挂起。
			4. synchronized阻塞其他锁是一个用户态切换到内核态的过程,而synchronized的使用就会导致上下文的切换。   

	(2)synchronized的内存定义
			
			1. 进入synchronized内存语义:将线程的私有内存删除直接从主内存中获取变量
			2. 退出synchronized内存语义:在synchronized中直接把变量的修改刷新到主内存中
  	
  	(3)原理
  			
  			1.	 前提:每个对象都有一个监视器锁,当监视器锁被占用的时候就会处于锁定的状态
  			2.	方法同步:通过acc_synchronized是否被设置,如果设置了执行线程先获取对象监视器,获取成功了执行方法体,
  				方法执行完再释放对象监视器。再方法执行期间,其他任何线程都无法获得同一个监视器对象。
  			3. 代码块同步:monitorenter 和monitorexit 指令实现
  			4. 重入型:每个对象拥有一个计数器,当线程获取该对象锁的后,计数器加一,释放后减一

2.6 java中volatile关键字

synchronized 阻塞其他锁,会造成上下文切换的开销,所以java提供了弱形式的同步volatile。
内存语义为:删除私有内存中的变量获取主内存直接刷新主内存

(1) 使用volatile的情况

		1. 读写变量值是没有加锁的
		2. 写入变量的时候不依赖当前值,因为volatile不支持原子性。

2.7 java中的原子操作

原子操作:要么都执行要么都不执行

2.8 java中的cas操作

解决排他锁和独占锁中因上下文切换带来的消耗问题

(1)cas(Object object,long valueOffset,long expect,long update)方法:object对象的内存位置,valueOffset
	偏移量,expect期望值,更新值。根据对象的内存位置和偏移量计算当前变量的值,如果和期待值相等就更新,否则不更新

(2)ABA问题:当线程A更新变量a从0到1又更新回0,这时候线程B的期待值是0,这就不是当时那个0了。

(3)解决ABA问题:AtomicStampedReference 类为每个变量配置了时间戳。

*2.9 Unsafe类

  • 之后会和后面的详细讲一下,很总要的知识点

2.10 Java指令重排序

int a=1;(1)
int b=2;(2)
int c=a+b;(3)
指令重排序只会保证(1)(2)在(3)前面执行而不会保证(1)和(2)的先后顺序

2.11 伪共享

为了解决cpu和主内存之间的运行速度差之间的关系,在cpu和主内存中会存在一个一级缓存或者多级高速缓存存储器,也就是上文中的二级缓存,该存储器中存储着多个变量,内部按存储,缓存行和主内存进行数据交换的单位。

	(1)什么是伪共享

		1. 多个变量存储到同一个缓存行,但是同一个缓存行同一时间只能由一个线程访问,相比于把一个变量放入一个缓存行
		   性能大大消耗

	(2)为什么会出现伪共享

		1. 多个变量存储到同一个缓存行,多个线程去访问同一个缓存行。
		   
	(3)如何避免伪共享
		
		1. 缓存行一共64字节,填充相应的字节

2.12 锁的概述

	(1)乐观锁和悲观锁
		
		1. 乐观锁:与悲观锁相反,在修改的过程中认为数据不会被其他线程修改
		2. 悲观锁:对外界的修改保持悲观的态度,认为在线程修改变量的过程一定有其他线程进来修改
		
	(2)公平锁和非公平锁
	
		1. 公平锁:按请求锁的时间顺序执行的锁,会带来额外的开销
		2. 非公平锁:按优先级来
	
	(3)独占锁和共享锁
	
		1. 独占锁:任何时候只能一个线程独占锁ReentrantLocak
		2. 共享锁:ReadWriteLock读写锁

	(4)可重入锁
	
		1. 定义:一个线程再次获得自己已经独占的锁时候不会被阻塞
		2. 原理:当一个线程获得一个锁的时候,会标示该线程,并且记录线程进入的次数。当次数为0时,标示便记录为null,
		   当进入是加一。

	(5)自旋锁/自适应自旋锁
	
		1. 自旋锁定义:一个线程占用锁,而另一个线程想要请求时会被阻塞而不马上阻塞自己,线程不放弃cpu的执行权,在指定的次数内
		   请求该锁,如果无法请求到便阻塞,这种方法以cpu的占用来换取上下文切换的消耗。
			缺点:
					1.  很多线程,很少处理器,自旋存在浪费
					2.   密集型任务,自旋占用cpu得不偿失
					3.   锁持有的时间长,白白浪费自旋占用的cpu时间
		2. 自适应自旋锁:如果一个线程已经经常通过自旋的方式获取过某一个锁,现在该锁正在被其他线程持有,虚拟机便认为该锁有机会通
			过自旋的方式获取,进而他将拥有更长的自旋时间,相反的,这个线程通过自旋方式获取该锁的次数比较少,成功率低的话,虚拟
			机将会减少他自旋的时间,甚至取消自旋的过程。
	(6)偏向锁->轻量级锁->重量锁
		1. 偏向锁:无竞争情况下,且将来只有第一个申请锁的线程会使用锁
		2. 轻量锁:无实际竞争,多个线程交替使用锁,允许短时间的锁的竞争
		3. 重量锁:有实际的竞争,且锁竞争的时间长
		    膨胀式的锁分配策略
		4.  定义:一个线程频繁访问一段同步代码,这个线程在访问的时候就可以立刻获得该锁,其他线程想要获得该锁的时候,该锁
			就转变为轻量级锁,其他线程通过自旋的方式获取该锁,如果自旋到一定次数没办法获取该锁的时候锁就会转化为重量级锁
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值