Java并发编程——线程带来的风险
在并发中有两种方式,一是多进程,二是多线程,但是线程相比进程花销更小且能共享资源。
多线程将会带来几个问题:
一、安全性问题。
线程安全性可能是非常复杂的,多线程中的操作执行顺序是不可预测的,甚至会产生奇怪的结果,另外由于存在指令重排序的可能,因此实际情况会很糟糕。
有一种常见的并发安全问题叫“竞态条件”。由于多个线程要共享相同的内存地址空间,并且是并发运行,因此它们可能会访问或修改其他线程正在使用的变量。这带来的极大的便利,但是也有巨大的风险:线程会由于无法预料的数据变化而发生错误。当多个线程同时访问和修改相同的变量时,将会在串行编程模型中引入非串行因素,而这种非串行性是很难分析的。要使多线程程序的行为可预测,必须对共享变量的访问操作进行协同,这样才不会在线程之间发生彼此干扰。
例如使用 synchronized 关键字来同步;
public class Value {
@GuardedBy("this") private int value;
public synchronized int getNext(){
return value++;
}
}
@GuardedBy(lock) 指明对象或变量受哪个锁保护
二、活跃性问题
线程会导致一些在单线程程序中不会出现的问题,那就是活跃性问题。
自己的理解的“活跃性问题”:即线程的活跃性,线程能够有意义的在正常的按设计工作。
安全性问题的含义是“永远不发生糟糕的事情”,而活跃性则关注另外一个目标:“某件正确的事情最终会发生”。当某个操作无法继续执行下去时,就会发生活跃性问题。在串行程序中,活跃性问题的一种就是无意中造成的无限循环,使得不能按照设计的工作进行,执行不到后面的代码。或者由于资源竞争而导致的死锁等。
活跃性问题同安全性问题同样难以分析,因为依赖于不同线程的事件发生时序,在测试中不总是能够重现。
三、性能问题
活跃性意味着某件正确的事情会中会发生,但却不够好,因为我们希望正确的事情尽快发生。性能问题包括多个方面,例如服务时间过长,响应不灵敏,吞吐率过低等等。
所以多线程需要良好的设计来提升线程的性能,但无论如何线程总会带来额外的开销,由于多线程之间的调度会频繁地出现上下文切换操作,保存和恢复执行上下文,线程之间共享数据时需要同步等等。
要做好并发应用程序就必须时刻注意和避免以上的问题,对于并发的学习还有很多东西需要了解学习。
浙公网安备 33010602011771号