没有合适的资源?快使用搜索试试~ 我知道了~
1. 保证可见性 2. 不保证原子性 3. 禁止指令重排
资源详情
资源评论
资源推荐
JUC多线程及高并发
JUC多线程及高并发
一、请你谈谈对volatile的理解
1、volatile是java虚拟机提供的轻量级的同步机制
2、JMM(java内存模型)
3、你在那些地方用过volatile
二、CAS你知道吗
1、compareAndSet----比较并交换
2、CAS底层原理?对Unsafe的理解
3、CAS缺点
三、原子类AtomicInteger的ABA问题?原子更新引用?
1、ABA如何产生
2、如何解决?原子引用
3、时间戳的原子引用
四、我们知道ArrayList是线程不安全的,请编写一个不安全的案例并给出解决方案
1、线程不安全
2、导致原因
3、解决方法:**CopyOnWriteArrayList
五、公平锁、非公平锁、可重入锁、递归锁、自旋锁?手写自旋锁
1、公平锁、非公平锁
2、可重入所(递归锁)
3、独占锁(写锁)/共享锁(读锁)/互斥锁
4、自旋锁
六、CountDownLatch/CyclicBarrier/Semaphore使用过吗
1、CountDownLatch(火箭发射倒计时)
2、CyclicBarrier(集齐七颗龙珠召唤神龙)
3、Semaphore信号量
七、阻塞队列
1、队列和阻塞队列
2、为什么用?有什么好处?
3、BlockingQueue的核心方法
4、架构梳理+种类分析
5、用在哪里
6、synchronized和lock有什么区别?用新的lock有什么好处?请举例
八、线程池用过吗?ThreadPoolExecutor谈谈你的理解
1、Callable接口的使用
2、为什么使用线程池
3、线程池如何使用
4、线程池的几个重要参数介绍
5、线程池的底层工作原理
九、线程池用过吗?生产上你如何设置合理参数
1、线程池的拒绝策略
2、你在工作中单一的/固定数的/可变的三种创建线程池的方法,用哪个多
3、你在工作中时如何使用线程池的,是否自定义过线程池使用
4、合理配置线程池你是如何考虑的?
十、死锁编码及定位分析
一、请你谈谈对volatile的理解
Package java.util.concurrent ---> AtomicInteger Lock ReadWriteLock
1、volatile是java虚拟机提供的轻量级的同步机制
保证可见性、不保证原子性、禁止指令重排
1. 保证可见性
当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看到修改的值
当不添加volatile关键字时示例:
package com.jian8.juc;
import java.util.concurrent.TimeUnit;
/**
* 1验证volatile的可见性
* 1.1 如果int num = 0,number变量没有添加volatile关键字修饰
* 1.2 添加了volatile,可以解决可见性
*/
public class VolatileDemo {
public static void main(String[] args) {
visibilityByVolatile();//验证volatile的可见性
}
/**
* volatile可以保证可见性,及时通知其他线程,主物理内存的值已经被修改
*/
public static void visibilityByVolatile() {
MyData myData = new MyData();
//第一个线程
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t come in");
try {
//线程暂停3s
TimeUnit.SECONDS.sleep(3);
myData.addToSixty();
System.out.println(Thread.currentThread().getName() + "\t update
value:" + myData.num);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}, "thread1").start();
//第二个线程是main线程
while (myData.num == 0) {
//如果myData的num一直为零,main线程一直在这里循环
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
输出结果:
当我们加上 volatile 关键字后, volatile int num = 0; 输出结果为:
2. 不保证原子性
原子性:不可分割、完整性,即某个线程正在做某个具体业务时,中间不可以被加塞或者被分割,需要整体完
整,要么同时成功,要么同时失败
验证示例(变量添加volatile关键字,方法不添加synchronized):
System.out.println(Thread.currentThread().getName() + "\t mission is over,
num value is " + myData.num);
}
}
class MyData {
// int num = 0;
volatile int num = 0;
public void addToSixty() {
this.num = 60;
}
}
39
40
41
42
43
44
45
46
47
48
49
50
thread1 come in
thread1 update value:60
//线程进入死循环
1
2
3
thread1 come in
thread1 update value:60
main mission is over, num value is 60
//程序没有死循环,结束执行
1
2
3
4
package com.jian8.juc;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 1验证volatile的可见性
* 1.1 如果int num = 0,number变量没有添加volatile关键字修饰
* 1.2 添加了volatile,可以解决可见性
*
* 2.验证volatile不保证原子性
* 2.1 原子性指的是什么
* 不可分割、完整性,即某个线程正在做某个具体业务时,中间不可以被加塞或者被分割,需要整体完
整,要么同时成功,要么同时失败
*/
public class VolatileDemo {
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {
// visibilityByVolatile();//验证volatile的可见性
atomicByVolatile();//验证volatile不保证原子性
}
/**
* volatile可以保证可见性,及时通知其他线程,主物理内存的值已经被修改
*/
//public static void visibilityByVolatile(){}
/**
* volatile不保证原子性
* 以及使用Atomic保证原子性
*/
public static void atomicByVolatile(){
MyData myData = new MyData();
for(int i = 1; i <= 20; i++){
new Thread(() ->{
for(int j = 1; j <= 1000; j++){
myData.addSelf();
myData.atomicAddSelf();
}
},"Thread "+i).start();
}
//等待上面的线程都计算完成后,再用main线程取得最终结果值
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (Thread.activeCount()>2){
Thread.yield();
}
System.out.println(Thread.currentThread().getName()+"\t finally num value
is "+myData.num);
System.out.println(Thread.currentThread().getName()+"\t finally atomicnum
value is "+myData.atomicInteger);
}
}
class MyData {
// int num = 0;
volatile int num = 0;
public void addToSixty() {
this.num = 60;
}
public void addSelf(){
num++;
}
AtomicInteger atomicInteger = new AtomicInteger();
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
执行三次结果为:
源代码 编译器优化的重排 指令并行的重排 内存系统的重排 最终执行的指令
线程1 线程2
x = a; y = b;
b = 1; a = 2;
结 果 x = 0 y=0
3. 禁止指令重排
有序性:在计算机执行程序时,为了提高性能,编译器和处理器常常会对指令做重拍,一般分以下三种
单线程环境里面确保程序最终执行结果和代码顺序执行的结果一致。
处理器在进行重排顺序是必须要考虑指令之间的数据依赖性
多线程环境中线程交替执行,由于编译器优化重排的存在,两个线程中使用的变量能否保证一致性时无法确定
的,结果无法预测
重排代码实例:
声明变量: int a,b,x,y=0
如果编译器对这段程序代码执行重排优化后,可能出现如下情况:
public void atomicAddSelf(){
atomicInteger.getAndIncrement();
}
}
68
69
70
71
//1.
main finally num value is 19580
main finally atomicnum value is 20000
//2.
main finally num value is 19999
main finally atomicnum value is 20000
//3.
main finally num value is 18375
main finally atomicnum value is 20000
//num并没有达到20000
1
2
3
4
5
6
7
8
9
10
剩余39页未读,继续阅读
林祈墨
- 粉丝: 31
- 资源: 326
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0