道多线程能并发的处理多个任务,有效地提高复杂应用程序的性能,在实际开发中扮演着十分重要的角色
但是使用多线程也带来了很多风险,并且由线程引起的问题往往在测试中难以发现,到了线上就会造成重大的故障和损失
下面我会结合几个实际案例,帮助大家在工作做规避这些问题
多线程问题
首先介绍下使用的多线程会有哪些问题
使用多线程的问题很大程度上源于多个线程对同一变量的操作权,以及不同线程之间执行顺序的不确定性
《Java并发编程实战》这本书中提到了三种多线程的问题:安全性问题、活跃性问题和性能问题
安全性问题
例如有一段很简单的扣库存功能操作,程环境下,这个方法能正确工作,但在多线程环境下,就会导致错误的结果
--count看上去是一个操作,但实际上它包含三步(读取-修改-写入):
-
读取count的值
-
将值减一
-
最后把计算结果赋值给count
如下图展示了一种错误的执行过程,当有两个线程1、2同时执行该方法时,它们读取到count的值都是10,最后返回结果都是9;意味着可能有两个人购买了商品,但库存却只减了1,这对于真实的生产环境是不可接受的上面例子这样由于不恰当的执行时序导致不正确结果的情况,是一种很常见的并发安全问题,被称为竞态条件
decrement()方法这个导致发生竞态条件的代码区被称为临界区
避免这种问题,需要保证读取-修改-写入这样复合操作的原子性
在Java中,有很多方式可以实现,比如使用synchronize内置锁或ReentrantLock显式锁的加锁机制、使用线程安全的原子类、以及采用CAS的方式等
活跃性问题
活跃性问题指的是,某个操作因为阻塞或循环,无法继续执行下去
最典型的有三种,分别为死锁、活锁和饥饿
死锁
最常见的活跃性问题是死锁
死锁是指多个线程之间相互等待获取对方的锁,又不会释放自己占有的锁,而导致阻塞使得这些线程无法运行下去就是死锁,它往往是不正确的使用加锁机制以及线程间执行顺序的不可预料性引起的
(编辑:宁德站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|