观看《Java并发编程的艺术》所做笔记
并发编程的挑战
上下文切换
概念
上下文切换:线程间的切换
线程切换前需要保持该线程的状态,这样下次切换回来的时候可以再加载到这个线程的状态
并发编程并不一定快,因为创建线程和上下文切换线程都需要开销,所以在某些情况下,并发执行并不一定快过串行执行
如何减少上下文切换
- 避免使用锁: 多线程竞争锁时,会引起上下文切换(比如当前线程没拿到锁,它就挂起该线程,切换)
- CAS操作: CAS操作是非阻塞式同步,不会使用锁
- 使用最少线程: 避免创建不需要的线程,避免大多数线程都在
WAITING
状态,使用时分配的时间片短,频繁的上下文切换 - 协程: 单线程中多任务调度,多任务在单线程中切换
死锁
查看死锁发生位置
/**
* @author Tc.l
* @Date 2020/11/26
* @Description:
*/
public class DeadLockTest {
static String A = "A";
static String B = "B";
public static void main(String[] args) {
new Thread(()->{
synchronized (A){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (B){
System.out.println("A");
}
}
}).start();
new Thread(()->{
synchronized (B){
synchronized (A){
System.out.println("BBBB");
}
}
}).start();
}
}
jps -l
查看进程号
jstack 进程号
查看堆栈信息
可以看到发现Java死锁
D:\代码\Java并发编程的艺术>jps -l
10900 org.jetbrains.idea.maven.server.RemoteMavenServer
1108 1²̵ս.DeadLockTest
5336 sun.tools.jps.Jps
15852
D:\代码\Java并发编程的艺术>jstack 1108
2020-11-26 21:46:19
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.191-b12 mixed mode):
"DestroyJavaVM" #14 prio=5 os_prio=0 tid=0x0000000003482800 nid=0x748 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Thread-1" #13 prio=5 os_prio=0 tid=0x000000001d6bf800 nid=0x37bc waiting for monitor entry [0x000000001e06f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at 1²̵ս.DeadLockTest.lambda$main$1(DeadLockTest.java:31)
- waiting to lock <0x00000007810cb208> (a java.lang.String)
- locked <0x00000007810cb238> (a java.lang.String)
at 1²̵??.DeadLockTest$$Lambda$2/1078694789.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"Thread-0" #12 prio=5 os_prio=0 tid=0x000000001d6be800 nid=0x3bd4 waiting for monitor entry [0x000000001df6f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at 1²̵ս.DeadLockTest.lambda$main$0(DeadLockTest.java:22)
- waiting to lock <0x00000007810cb238> (a java.lang.String)
- locked <0x00000007810cb208> (a java.lang.String)
at 1²̵ս.DeadLockTest$$Lambda$1/1324119927.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
...
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x000000001a9a21e8 (object 0x00000007810cb208, a java.lang.String),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x000000001a9a35d8 (object 0x00000007810cb238, a java.lang.String),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at 1²̵ս.DeadLockTest.lambda$main$1(DeadLockTest.java:31)
- waiting to lock <0x00000007810cb208> (a java.lang.String)
- locked <0x00000007810cb238> (a java.lang.String)
at 1²̵ս.DeadLockTest$$Lambda$2/1078694789.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"Thread-0":
at 1²̵ս.DeadLockTest.lambda$main$0(DeadLockTest.java:22)
- waiting to lock <0x00000007810cb238> (a java.lang.String)
- locked <0x00000007810cb208> (a java.lang.String)
at 1²̵ս.DeadLockTest$$Lambda$1/1324119927.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.
避免死锁:
- 避免一个线程同时获取多个锁
- 避免一个线程在锁内同时获取多个资源
- 尝试使用定时锁