什么是线程安全
- 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
多线程的几种实现方式
- 继承Thread类,或,实现Runnable接口
- 至于哪个好,不用说一定是后者好,由于实现接口的方式比继承类的方式更灵活,也能减少程序之间的耦合度
start()方法和run()方法的区别
- start()方法用来启动新创建的线程,被创建的线程状态变为可运行状态,当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动, 如果我们调用了Thread的run()方法,它的行为就会和普通的方法一样。
多线程怎么防止死锁(首先要明白造成死锁的四个条件)
-
互斥使用:一个资源每次只能给一个进程使用。(一夫一妻制)
-
不可抢占:资源申请者不能强行的从资源占有者手中夺取资源,只能由占有者自愿释放(只能自愿不能强行)
-
请求和保持:一个进程在申请新的资源的同时保持对原有资源的占有(吃着碗里,看着锅里)
-
循环等待:存在一个进程等待队列{P1, P2, … ,Pn}(备胎排队)
-
解决办法:
-
加锁顺序:这种方式需要你事先知道所有可能会用到的锁,但总有些时候是无法预知的。(找下一个备胎必须要得到当前备胎的允许)
-
例子: 线程2和3只有获取了锁A后才能尝试获取锁C(获取锁A是获取锁C的必要条件)。线程1已经拥有锁A,所以线程2和3需要一直等到锁A被释放。然后在尝试对B或C加锁之前,必须成功地对A加了锁。
-
加锁时限:线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁(类似一夜情)
-
死锁检测:当一个线程获得了锁或者请求锁,会在线程和锁相关的数据结构中(map等等)将其记下,当一个线程请求锁失败时,遍历锁的关系图看看是否有死锁发生,当检测出死锁时,要么释放所有锁,回退,要么线程设置优先级。(检查前车主是否有备用钥匙)
-