如何干掉多线程

本文探讨了干掉多线程的方法及其带来的益处,包括减少锁和争用,提高系统稳定性、可读性和易维护性。通过阶段模式划分系统,实现了系统在I/O阶段与非I/O阶段的分离,从而有效利用CPU资源,减少线程切换带来的损耗,并通过Future、Callback、Actor等技术实现这一目标。
 

如何干掉多线程
干掉多线程的目的是为了干掉锁,干掉争用,减少开发的难度及提高系统的稳定性,可理解性,易维护性。


以阶段来划分系统的话,有多种划分方法。比如业务意义上的阶段,或模块意义上的阶段。但是这样的划分总是有点画蛇添足的感觉:计算机并不懂业务,它也不懂模块。它什么都不懂。它懂的只有指令。两种指令:内存指令与IO指令。本来这两者都只是处理器的事情,跟我并没有关系。但是IO指令会将线程挂起,线程跟我有关系。因为它承载我的“任务”。


这样划分的话,我至少得到两种阶段:IO阶段与非IO阶段。具体设计可能采用2个阶段,也可能采用10个阶段。但所有的阶段要么属于I/O阶段要么不属于。


采用阶段模式的好处是,系统没有并发。系统存在的只有一些阶段与中间结果。即使在面向对象的系统中,经过适当的设计仍然可以完全避免掉阶段之间的数据共享(因为面向对象的系统是有状态的系统,所以很容易产生数据共享----相反的是,这却正是面向过程系统最大的好处。因为它无状态所以使得服务器端的开发异常容易----同时也证明了面向对象开发的高成本特征:高开发成本,低进化成本。而面向过程则是:低开发成本,高进化成本)的情况。


多道程序设计即多线(进)程本来就是为了I/O适配而产生的。目的是使得系统在等待I/O设备就绪以前有别的事情可以做,以致于不浪费系统在等待I/O期间的CPU周期。但是分阶段一样可以做到它。两者的区别不过是一个是从纵向对用户任务进行的切分,一个则是从横向进行的切分。而两者在提高CPU利用率的方法这一点上其实是一致的:都是“分而治之”。分开的部分可以独立运行,CPU利用率自然就提高了。


实现技术上,有几种模式可以考虑应用于这种分阶段设计:Future, Callback, Actor。见:


http://www.cnblogs.com/uptownBoy/articles/1772483.html(什么是Future)


I/O被拿出来单独处理的好处有:


1,在以数据库为中心的系统中,如果使用事务的话,几乎不需要同步。即使需要同步,同步也只存在于本来阻塞就很严重的I/O线程,不影响其它线程。同步被局限在I/O层还有一个好处是,系统更稳定。因为这样的系统总比那些通常到处都是同步的面向对象系统好得多(什么是线程安全?谁来负责那么多的同步?在一个面向对象的系统中。。。);


2,集中在一起的I/O操作更容易管理或优化;


3,因I/O阻塞而产生的线程开销最小化。实际上,I/O将只阻塞在自己上面。也就是I/O将相互阻塞。也就是说,系统的堆栈空间浪费被最小化;


4,如果线程数量被设定为与处理器相同的数量的话,在这种模式下,线程之间的切换会很少发生。大幅减少了因线程切换产生的处理器资源直接损失以及间接损失如缓存失效,内存屏障,寄存器重新载入,指令重排序等。
 

在PL/SQL中终止线可依据不同场景选择不同方法: - **查询session杀不掉时强制终止线**: - 先通过以下查询语句获取相关进信息:`select spid, osuser, s.program from v$session s,v$process p where s.paddr=p.addr and s.sid=30;` - 在不同操作系统执行相应操作: - 在Unix上,以root身份执行命令`kill -9 <spid>`(`<spid>`为查询出的进号),执行后PL/SQL会断开连接,查询终止 [^1]。 - 在Windows(Unix也适用),使用orakill命令,语法为`orakill sid thread`,其中`sid`是要杀死的进属于的实例名,`thread`是要杀掉的线号(即查询出的`spid`)。例如`c:\>orakill orcl 12345` [^1]。 - **干掉执行线**: - 先查询锁住的表以及对应的session状态。当状态为`active`时,可使用“active时初级杀掉死锁线SQL”杀掉正在执行的线;很多时候运行后状态会变为`killed`,此时数据库在进行回滚操作,若没耐心或赶时间,可执行“kill时杀掉死锁线命令”,该命令在数据库服务器机子上执行,用于杀掉指定线,需慎重操作 [^2]。 - **批量杀死sleep线**:可使用PL/SQL代码定义游标来批量杀死某些会话。示例代码如下: ```plsql cursor cur_session is select sid,serial# from v$session where program ='plsqldev.exe'; --#定义cursor ``` 此代码通过游标筛选出`program`为`plsqldev.exe`的会话 [^3]。 - **杀死inactive线**:可以创建存储过来杀死符合特定条件的非活动线。示例代码如下: ```plsql CREATE OR REPLACE PROCEDURE "KILL_SESSION" AS v_sid number; v_serial number; killer varchar2(1000); CURSOR cursor_session_info is select sid,serial# from v$session where type!='BACKGROUND' and status='INACTIVE' and last_call_et>2700 and username='STPT' and machine='wonders_svr2'; BEGIN open cursor_session_info; loop fetch cursor_session_info into v_sid,v_serial; exit when cursor_session_info%notfound; killer:='alter system disconnect session '''||v_sid||','||v_serial||''' post_transaction immediate'; execute immediate killer; end loop; dbms_output.PUT_LINE(cursor_session_info%rowcount||' users with idle_time>2700s have been killed!'); close cursor_session_info; END; ``` 该存储过会杀死类型不是`BACKGROUND`、状态为`INACTIVE`、空闲时间超过2700秒、用户名是`STPT`且机器名为`wonders_svr2`的会话 [^4]。 - **处理杀不掉锁的进**:可通过以下查询语句查看相关信息: ```plsql select c.owner, c.object_name, c.object_type, b.sid, b.serial#, b.status, b.osuser, b.machine from v$locked_object a, v$session b, dba_objects c where b.sid = a.session_id and a.object_id = c.object_id; ``` 根据查询结果进一步处理杀不掉锁的进 [^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值