欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

进程和线程

程序员文章站 2024-01-03 08:19:22
【描述】线程和进程是一个老生常谈的话题,线程和进程的区别和优缺点有哪些?线程最多可以开多少个? 【解析】 1 区别  线程是CPU调度的最小单位,进程是资源分配的最...

【描述】线程和进程是一个老生常谈的话题,线程和进程的区别和优缺点有哪些?线程最多可以开多少个?

【解析】

1 区别

 线程是CPU调度的最小单位,进程是资源分配的最小单位。进程是线程的容器,真正完成代码执行的是线程,而进程则作为线程的执行环境。在32位的Windows操作系统中,系统要为每一个进程分配私有的232=4GB的虚拟地址空间。但实际上只有2GB的空间被用户分区使用,另外2GB空间被用于内核代码、设备驱动程序等内核分区。在进程中,线程共享用户分区这一地址空间。

2 优缺点

在Windows系统中,对于多进程程序而言,系统要为进程分配私有的4GB虚拟地址空间,占用的资源较多。而对于多线程的程序,多线程共享同一进程的地址空间,因此占用的资源较少。当进程切换时,需要交换整个地址空间,而线程之间切换只是执行环境的改变,因此效率较高。整体而言,在Windows系统中,多线程优于多进程,毕竟Windows系统是从多线程开始的。

Linux系统中,采用POSIX标准,Unix家族都是从多进程过来的。多进程调度开销比多线程调度开销,没有显著区别。

一个形象的比喻,

多进程是立体交通系统,虽然造价高,上坡下坡多耗点油,但是不堵车。

多线程是平面交通系统,造价低,但红绿灯太多,老堵车。

所谓的耗油多是指CPU的主频,但现在主频已不是问题,而内存也是越来越大。我们更希望行车过程畅通无阻。

3 线程栈

线程栈用于维护线程在执行代码时需要的所有函数参数和局部变量。在32位的系统中,进程中,线程最多能开多少个?

这个没有固定的答案,

线程的大小 = 进程用户空间/线程栈的大小。

在Windows平台默认的栈大小为1M,以此计算,理论上,可以开辟2GB/1M=2048个线程。但实际上,是无法做到的。因为有其他部分的消耗。

在Linux平台,如Fedora 10,利用ulimit -a指令可以查看堆栈的大小,结果为

stack size              (kbytes, -s) 10240
也就是10M。以此计算,最多开辟2GB/10MB=204个线程。另外查阅文档,反映Linux平台的栈默认大小应该是8192KB,而不是10M。

 

【实例剖析】

到底可以开多少个,不妨测试一下:

测试环境:虚拟机+512MB(虚拟内存估计是1024MB)

test.c

[html]
#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
#include <assert.h> 
 
void *start_routine(void *param) 

    int data = *(int *)param; 
    printf("%s:%d\n", __func__, data); 
    return NULL; 

 
#define THREADS_NR 1024 
void create_test_threads() 

    int i = 0; 
    int ret1 = 0; 
    void *ret2 = NULL; 
 
    pthread_t ids[THREADS_NR] = {0}; 
     
    for(i = 0; i < THREADS_NR; i++) 
    { 
        ret1 = pthread_create(ids + i, NULL, start_routine, &i); 
    } 
 
    for(i = 0; i < THREADS_NR; i++) 
    { 
        pthread_join(ids[i], &ret2); 
    } 
 
    return ; 

 
int main(int argc, char **argv) 

    create_test_threads(); 
 
    return 0; 

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>

void *start_routine(void *param)
{
 int data = *(int *)param;
 printf("%s:%d\n", __func__, data);
 return NULL;
}

#define THREADS_NR 1024
void create_test_threads()
{
 int i = 0;
 int ret1 = 0;
 void *ret2 = NULL;

 pthread_t ids[THREADS_NR] = {0};
 
 for(i = 0; i < THREADS_NR; i++)
 {
  ret1 = pthread_create(ids + i, NULL, start_routine, &i);
 }

 for(i = 0; i < THREADS_NR; i++)
 {
  pthread_join(ids[i], &ret2);
 }

 return ;
}

int main(int argc, char **argv)
{
 create_test_threads();

 return 0;
}
Makefile

[html]
src = test.c 
target = test 
temp = $(wildcard *~) 
flag = PTHREAD_TEST 
 
all:$(src) 
    gcc -g -pthread -D$(flag) $^ -o $(target) 
 
clean: 
    rm $(temp) $(target) 

src = test.c
target = test
temp = $(wildcard *~)
flag = PTHREAD_TEST

all:$(src)
 gcc -g -pthread -D$(flag) $^ -o $(target)

clean:
 rm $(temp) $(target)
运行结果

[html]
start_routine:300 
start_routine:301 
start_routine:302 
start_routine:303 
start_routine:304 
段错误 

start_routine:300
start_routine:301
start_routine:302
start_routine:303
start_routine:304
段错误
 

实验证实在该的环境中,最多可以开辟305个线程。利用GDB调试:

gdb test

[html]
start_routine:303 
[Thread 0xbe409b90 (LWP 11075) exited] 
[New Thread 0xbee0ab90 (LWP 11076)] 
start_routine:304 
[Thread 0xbee0ab90 (LWP 11076) exited] 
[New Thread 0xbf80bb90 (LWP 11077)] 
start_routine:565 
[Thread 0xbf80bb90 (LWP 11077) exited] 
 
Program received signal SIGSEGV, Segmentation fault. 
0x00581b07 in pthread_join () from /lib/libpthread.so.0 
Missing separate debuginfos, use: debuginfo-install glibc-2.9-2.i686 
(gdb) bt 
#0  0x00581b07 in pthread_join () from /lib/libpthread.so.0 
#1  0x0804859f in create_test_threads () at test1.c:29 
#2  0x080485d1 in main () at test1.c:37 
(gdb) frame 1 
#1  0x0804859f in create_test_threads () at test1.c:29 
29          pthread_join(ids[i], &ret2); 
(gdb) p ret1 
$4 = 11 
(gdb) p ret2 
$5 = (void *) 0x0 

start_routine:303
[Thread 0xbe409b90 (LWP 11075) exited]
[New Thread 0xbee0ab90 (LWP 11076)]
start_routine:304
[Thread 0xbee0ab90 (LWP 11076) exited]
[New Thread 0xbf80bb90 (LWP 11077)]
start_routine:565
[Thread 0xbf80bb90 (LWP 11077) exited]

Program received signal SIGSEGV, Segmentation fault.
0x00581b07 in pthread_join () from /lib/libpthread.so.0
Missing separate debuginfos, use: debuginfo-install glibc-2.9-2.i686
(gdb) bt
#0  0x00581b07 in pthread_join () from /lib/libpthread.so.0
#1  0x0804859f in create_test_threads () at test1.c:29
#2  0x080485d1 in main () at test1.c:37
(gdb) frame 1
#1  0x0804859f in create_test_threads () at test1.c:29
29   pthread_join(ids[i], &ret2);
(gdb) p ret1
$4 = 11
(gdb) p ret2
$5 = (void *) 0x0

错误发生在创建时,错误码为11

查看errno.h

利用find查看路劲

(1)  find / -name errno.h 2>/dev/null

[html]
/usr/src/kernels/2.6.27.5-117.fc10.i686/include/linux/errno.h 
/usr/src/kernels/2.6.27.5-117.fc10.i686/include/asm-x86/errno.h 
/usr/src/kernels/2.6.27.5-117.fc10.i686/include/asm-generic/errno.h 

/usr/src/kernels/2.6.27.5-117.fc10.i686/include/linux/errno.h
/usr/src/kernels/2.6.27.5-117.fc10.i686/include/asm-x86/errno.h
/usr/src/kernels/2.6.27.5-117.fc10.i686/include/asm-generic/errno.h
(2) 查看源文件

执行

cat /usr/src/kernels/2.6.27.5-117.fc10.i686/include/asm-generic/errno.h

发现11定义在同级目录下errno-base.h文件

查看

cat  /usr/src/kernels/2.6.27.5-117.fc10.i686/include/asm-generic/errno-base.h

[html] view plaincopyprint?#define EAGAIN          11      /* Try again */ 

#define EAGAIN          11      /* Try again */
利用man pthread_create查看,

[html]
ERRORS 
       The pthread_create() function shall fail if: 
 
       EAGAIN The system lacked the  necessary  resources  to  create  another 
              thread,  or  the  system-imposed  limit  on  the total number of 
              threads in a process {PTHREAD_THREADS_MAX} would be exceeded. 
 
       EINVAL The value specified by attr is invalid. 
 
       EPERM  The caller does not  have  appropriate  permission  to  set  the 
              required scheduling parameters or scheduling policy. 
 
       The  pthread_create()  function  shall  not  return  an  error  code of 
       [EINTR]. 
 
       The following sections are informative. 

ERRORS
       The pthread_create() function shall fail if:

       EAGAIN The system lacked the  necessary  resources  to  create  another
              thread,  or  the  system-imposed  limit  on  the total number of
              threads in a process {PTHREAD_THREADS_MAX} would be exceeded.

       EINVAL The value specified by attr is invalid.

       EPERM  The caller does not  have  appropriate  permission  to  set  the
              required scheduling parameters or scheduling policy.

       The  pthread_create()  function  shall  not  return  an  error  code of
       [EINTR].

       The following sections are informative.


 

上一篇:

下一篇: