线程带来的风险

线程安全性问题

多线程环境下 +多个线程共享一个资源+对资源进行非原子性操作。

以上三者都存在就会发生线程安全性问题

如文中的卖火车票问题:http://blog.****.net/zengmingen/article/details/53217229

原因是:一行java代码转成.class字节码文件后是多行的,程序在执行的时候,行字节码文件里一行行执行。

当多个线程,A线程执行到100行,cpu时间片用完了,保留现场,cpu去了服务B线程了。

B线程执行也执行到了100行,cpu时间片用完了,保留现场,cpu去了服务C线程了。

下一轮时间片的时候,可能A,B的取值是一样的。

活跃性问题

死锁

经典的哲学家吃饭问题

5个哲学家坐一起边讨论哲学边吃饭,但是每个哲学家只有一只筷子,吃饭时需要问旁边的人借一只筷子。

正常是:一开始讨论哲学,要吃的哲学家问旁边的借一下筷子。

异常是:5位哲学家都停下讨论一起吃饭,谁也不借筷子,全饿死了。

都有资源,都不释放,导致无资源可用,死锁!

java自带的jconsole可以检测死锁

线程带来的风险

饥饿

餐厅就餐问题,餐厅卖饭窗口只有一个。一群没素质的人不排队硬挤,买到饭了也不走,结果后面挤不进去的,饿死了。

在线程里是优先级问题,优先级没搞好。

高优先级吞噬所有低优先级的CPU时间片
线程被永久堵塞在一个等待进入同步块的状态
等待的线程永远不被唤醒

如何尽量避免饥饿问题?
设置合理的优先级
使用锁来代替synchronized

活锁

活锁,其实和锁没有必然关系。活锁就像小猫追着自己的尾巴咬,虽然它一直在咬却一直没有咬到!活锁就是指线程一直处于运行(RUNNABLE)状态,但却是在做无用功,而这个线程本身要完成的任务却一直无法进展。活锁的一个典型例子是某些重试机制(实现地有问题)导致一个交易(请求)被不断地重试,而每次重试都是失败的(线程在最无用功),这就导致其他失败的交易无法得到重试的机会(任务无法进展)。

性能问题

cpu分配给各线程的时间,叫做时间片。这个时间片的时间是非常短的。

cpu在时间片完成后,cpu在切换到下一个线程之前需要做一些工作,如保留现场。这个比较消耗cpu资源。