不可饶恕错误之资源竞争

技术与开发

编者语:金融危机的到来让许多程序员也受到影响,在这样的大环境下,程序员还有好的机遇吗?有!而且是非常多的机遇!当前移动平台的程序开发如火如荼,特别是在苹果、Google等推出了平台开发工具后,进入这一领域的程序员越来越多,有的是想赚一些外快,有的是想在移动平台上功成名就,成为马化腾第二。

机遇就在眼前,你整装待发了吗?在此之前,还有什么需要注意的?小编跟以前进入此领域的程序员们交流时,他们首先给出的是忠告,编程时要避免犯一些不必要的错误,留下安全漏洞,造成功亏一篑。那又有哪些错误是我们需要避免的呢?看了不可饶恕编程错误系列,你就可以正式“出征”了!

数动连线程序员许勇:当前想入驻手机的程序非常多,其中有不少是需要使用到数据库的。如果一个程序出现多个进程同时抢用数据库的话(也就是大家常说的资源竞争),手机的性能导致它是挺不过去的,就会出现卡死、假死等症状。

例如,在手机中调用一个游戏,这个游戏却出现了资源竞争,游戏就打不了了,这个游戏也就不会被广大手机用户接受。大家从别的平台转到手机平台进行开发,可能因为环境不熟悉等原因犯了资源竞争错误,所以在正式推出程序前,应该做一下是否有资源竞争错误的测试。

什么是资源竞争

资源竞争是什么意思呢?它指的是同一个程序的多个并发进程互相等待对方拥有的所有资源,但这些并发进程在得到对方的资源前又不会释放自己占用的资源,这样便造成了每个进程都想得到资源却又得不到资源的状况,从而导致进程不能继续运行下去,整个程序无响应。

我们在设计程序的时候,最容易犯的资源竞争错误就是对数据库的并发操作,如果程序对访问数据库资源控制不当,造成资源竞争,便有可能造成部分入库数据丢失、占用大量数据库资源,导致访问缓慢异常、服务器宕机等问题。

手机的处理能力不能与台式电脑相提并论,如果设计的程序出现哪怕一点资源竞争,就可能导致手机假死,严重影响手机的操作,也会导致用户卸载有问题的程序。所以说,开发手机程序出现资源竞争错误,是不可饶恕的。

资源竞争错误代码分析

资源竞争是程序员很容易犯的错误。下面我们来看两个典型的资源竞争错误的代码。

代码1:同时锁定资源造成资源竞争

当两个进程正在等候彼此锁定的资源时就发生死锁错误。

1. 进程A通过将ID为20的雇员名字改成Tim来更新USERS表:

SQL>UPDATE USERS SET 姓名='Tim' WHERE id=20;

2.接着,进程A又将ID为25的雇员薪水改成5000元来更新USER表:

SQL>UPDATE USER SET 薪水=5000 WHERE id=25;

3. 进程B通过将雇员25的名改成Smith来更新该雇员。此时进程B被排在进程A在同一行上的锁后面等候着, 因此进程B的会话悬挂起来:

SQL>UPDATE USER SET 姓名='Smith' WHERE id=25;

4. 现在,进程B开始更新ID为20的雇员记录,并试图把他的薪水改成6000元:

SQL>UPDATE USER SET 薪水=6000 WHERE id=20;

这里进程B由于进程A已经锁住ID为20的记录,它必须等待进程A释放该资源,才能继续自己的更新记录操作。同样进程A要等进程B释放ID为25的记录才能继续自己的更新记录操作,这样就造成了资源竞争,系统将被悬挂起来。

正确方法:我们在这里应该尽量避免同时锁定两个资源,必须同时锁定两个资源时,要保证在任何时刻都应该按照相同的顺序来锁定资源。所以,我们在这里可以将正在操作的记录通过程序显示出来,避免其他进程再次操作。

代码2:权限上升导致资源竞争

1.进程A读进程表USER的一条ID为5的记录:

SQL>SELECT * FROM USER Where ID=5;

2.然后,进程A修改这条记录:

SQL> UPDATE USER SET 姓名='Smith' WHERE id=5;

3.这时,进程B也在修改该记录:

SQL> UPDATE USER SET薪水=6000 WHERE id=5;

在这里,进程A的事务锁由共享锁企图上升到独占锁(update),而进程B里的独占锁由于进程A有共享锁存在所以必须等进程A释放掉共享锁。进程A由于进程B的独占锁而无法上升到独占锁,同时也就不可能释放共享锁,于是出现资源竞争。

正确做法:应该让进程A进行先读后写类型的操作,在读取记录时要禁止修改操作,语法如下:SQL>SELECT * FROM USER WITH(UPDLOCK) Where ID=5;。

小编支招

如何避免资源竞争的出现呢?方法之一就是打破资源的互斥和不可剥夺这两个条件,例如允许多个进程同时访问某些资源。第二种方法,我们可以将资源分类按顺序排列,使进程在申请资源、保持资源时不形成环路。

第三种方法,我们还可以将各个进程所需要的资源预先分配好,如果某个进程资源得不到满足,则释放这个进程所占有的资源并将该进程按一定次序排序,等待其他进程释放资源后运行。当然,上面避免资源竞争的方法各有各的优势,但也有各自的缺点,大家在使用的时候按实际情况具体选择使用哪种方法。

总结

不可饶恕编程错误系列就到此结束了,我们讲了SQL注入漏洞错误、未转义错误、明文传输敏感信息错误、资源竞争错误,它们如果出现在手机程序中,会给手机用户带来严重的后果,大家一定要注意避免。此外,还有一些错误会在论坛的陈邓新编辑交流帖(http://bbs.shudoo.com/viewthread.php?tid=1585390)中一一讲解。