多线程--使单线程程序多线程化

来源:互联网 发布:清空datagridview数据 编辑:程序博客网 时间:2024/06/04 23:36

将单线程程序改写成多线程程序比直接写多线程程序需要更高的技巧


问题一:全局变量

对于全局变量,多线程程序可能在线程更新但尚未使用全局变量前进行了线程切换,并让新线程重新改写了该全局变量,这样就造成了原有数据的丢失

解决方案:

1、全面禁止全局变量,这显然是不现实的。

2、每个线程赋予其私有的全局变量,每个线程都保存一个全局变量的私有副本,以避免冲突。但多数语言不直接支持这样的变量,因此又有下面的几种方案

    (1)、依然在进程中使用全局变量,但是以函数参数的方式传递给线程,线程只使用形参而不是实际的全局变量

    (2)、引入新的库过程

3、POSIX使用一组库过程解决这个问题:

    create_global ("bufptr");    在堆空间上或在专门为调用线程所保留的特殊存储区替一个名为bufptr的指针分配存储空间,只有调用线程才可以访问,如果另一个线程创建了一个同名变量,这两个变量之间将不会产生冲突,因为他们保存在不同的存储空间

    set_global ("bufptr", &buf);    用buf所指向的值更新bufptr

    read_global ("bufptr");    返回一个存储在全局变量中的地址,这样就可以访问其中的数据了


问题二:库过程

很多库过程是不可重入的,即在执行到一半以后是不能重新开始执行的,比如内存分配过程malloc,在它维护内存表并开辟内存时,可能在某一时刻,内存表与实际的内存使用情况并不一致,此时如果切换线程并重新使用malloc开辟内存则很有可能造成无效指针的产生

解决方案:

1、重写库函数,这显然是不现实的

2、为每个过程提供一个包装器,该包装器设置一个二进制位以标志某个库正在使用中,这样其他所有调用这个库的线程都将陷入阻塞,虽然这个方案可行,但是这会极大的降低系统的并行性


问题三:信号

当线程完全是在用户空间实现时,内核将根本不知道有线程的存在,因此很难将信号发送给正确的线程

对于有些信号,如键盘中断,是应该让一个指定的线程捕捉他还是应该让所有线程都捕捉他?或者是创建新的弹出式线程?

在单线程的进程中,信号已经很难处理了,多线程环境中将更加困难


问题四:堆栈管理

很多系统中,当进程的堆栈溢出时,内核自动为该进程提供更多堆栈,但当每个进程中有多个线程时,就会有多个堆栈,如果内核不了解所有堆栈,将无法做出正确的分配,而进程有可能根本无法确定线程堆栈是否已经溢出


原创粉丝点击