@@ -397,9 +397,9 @@ class RunnableDemo implements Runnable {
397397
398398### 什么是线程死锁?
399399
400- 多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止 。
400+ 线程死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象。若无外力作用,它们都将无法推进下去 。
401401
402- 如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方的资源 ,所以这两个线程就会互相等待而进入死锁状态。
402+ 如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方持有的资源 ,所以这两个线程就会互相等待而进入死锁状态。
403403
404404![ 死锁] ( https://gitee.com/tysondai/img/raw/master/死锁.png )
405405
@@ -1121,3 +1121,28 @@ public final void lazySet(int i, int newValue)//最终 将index=i 位置的元
11211121- AtomicStampedReference:带有版本号的引用类型原子类。该类将整数值与引用关联起来,可用于解决原子的更新数据和数据的版本号,可以解决使用 CAS 进行原子更新时可能出现的 ABA 问题。
11221122- AtomicMarkableReference :原子更新带有标记的引用类型。该类将 boolean 标记与引用关联起来
11231123
1124+ ## 为什么要使用Executor线程池框架呢?
1125+
1126+ - 每次执行任务都通过new Thread()去创建线程,比较消耗性能,创建一个线程是比较耗时、耗资源的
1127+ - 调用new Thread()创建的线程缺乏管理,可以无限制的创建,线程之间的相互竞争会导致过多占用系统资源而导致系统瘫痪
1128+ - 直接使用new Thread()启动的线程不利于扩展,比如定时执行、定期执行、定时定期执行、线程中断等都不好实现
1129+
1130+ ## 如何停止一个正在运行的线程?
1131+
1132+ 1 . 使用共享变量的方式。共享变量可以被多个执行相同任务的线程用来作为是否停止的信号,通知停止线程的执行。
1133+ 2 . 使用interrupt方法终止线程。当一个线程被阻塞,处于不可运行状态时,即使主程序中将该线程的共享变量设置为true,但该线程此时根本无法检查循环标志,当然也就无法立即中断。这时候可以使用Thread提供的interrupt()方法,因为该方法虽然不会中断一个正在运行的线程,但是它可以使一个被阻塞的线程抛出一个中断异常,从而使线程提前结束阻塞状态。
1134+
1135+ ## 什么是Daemon线程?
1136+
1137+ 后台(daemon)线程,是指在程序运行的时候在后台提供一种通用服务的线程,并且这个线程并不属于程序中不可或缺的部分。因此,当所有的非后台线程结束时,程序也就终止了,同时会杀死进程中的所有后台线程。反过来说,只要有任何非后台线程还在运行,程序就不会终止。必须在线程启动之前调用setDaemon()方法,才能把它设置为后台线程。
1138+
1139+ 注意:后台进程在不执行finally子句的情况下就会终止其run()方法。
1140+
1141+ 比如:JVM的垃圾回收线程就是Daemon线程,Finalizer也是守护线程。
1142+
1143+ ## SynchronizedMap和ConcurrentHashMap有什么区别?
1144+
1145+ SynchronizedMap一次锁住整张表来保证线程安全,所以每次只能有一个线程来访问map。
1146+
1147+ JDK1.8 ConcurrentHashMap采用CAS和synchronized来保证并发安全。数据结构采用数组+链表/红黑二叉树。synchronized只锁定当前链表或红黑二叉树的首节点,支持并发访问、修改。
1148+ 另外ConcurrentHashMap使用了一种不同的迭代方式。当iterator被创建后集合再发生改变就不再是抛出ConcurrentModificationException,取而代之的是在改变时new新的数据从而不影响原有的数据 ,iterator完成后再将头指针替换为新的数据 ,这样iterator线程可以使用原来老的数据,而写线程也可以并发的完成改变。
0 commit comments