首页 > 代码库 > 多线程

多线程

1. 线程的概念

    线程是程序执行流的最小单元,也称为轻量级进程。
2. 进程的概念 

    计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础
3. 线程与进程的关系

    一个进程至少有一个线程,一个线程只属于一个进程。进程是系统进行资源分配和调度的一个单位,线程是进程的一个实体,线程除了拥有再运行中必不可少的资源(如程序计数器,一组寄存器和栈)不拥有任何系统资源,只能使用所属进程的资源

4. windows环境多线程

  4.1 windows创建线程API

HANDLE WINAPI CreateThread(
    __in_opt  LPSECURITY_ATTRIBUTES lpThreadAttributes,
    __in      SIZE_T dwStackSize,
    __in      LPTHREAD_START_ROUTINE lpStartAddress,
    __in_opt  LPVOID lpParameter,
    __in      DWORD dwCreationFlags,
    __out_opt LPDWORD lpThreadId
    );
  • lpThreadAttributes

  指向LPSECURITY_ATTRIBUTES结构体的指针,默认设为NULL,让线程使用默认的安全性。如果希望所有子线程能够继承线程对象的句柄,则必须设定LPSECURITY_ATTRIBUTES结构体,将它的bInHeriHandle初始化未TRUE。

  • dwStackSize

    设置初始栈的大小,默认设为0。

  • lpStartAddress

  指向LPTHREAD_START_ROUTINE指向的函数指针,即为新线程的起始地址。该函数的名称任意,但是函数类型必须遵照下面声明的形式:

typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(
    LPVOID lpThreadParameter
    );
  • lpParameter

  新线程调用函数的命令行参数。

  • dwCreationFlags

  用于控制线程创建的附加标记。可以使两个值之一:CRETE_SUSPENDED或0。如果是SUSPENDED,那么线程创建后将处于暂停状态。如果是0,线程在创建后立即运行。

  • lpThreadId

  指向一个变量,用来接受线程的ID。如果对线程ID不感兴趣可以直接设为NULL。

  注意:CreateThread()函数传回的值有两个,第一个值是返回值HANDLE,这个值是线程的HANDLE,是线程所在的进程中的局部变量,在不同的进程中是不唯一的,所以你不能直接跨进程的把一个线程的HANDLE传给另外一个进程中的线程让其使用。第二个值是由lpThreadId传回的线程ID,此值是一个全局变量,可以独一无二的表示系统中任意进程中的某个线程。比如调用AttachThreadInput()或PostThreadMessage()就需要用线程ID,而不能用线程的HANDLE。

      4.2 等待函数

            等待函数可使线程自愿进入等待状态,直到一个特定的内核对象变为已通知状态为止。

            

DWORD WaitForSingleObject(
     HANDLE hObject,
     DWORD dwMilliseconds
);
  • hObject

  标识一个能够支持被通知/未通知的内核对象(前面列出的任何一种对象都适用)。

  • dwMilliseconds

  允许该线程指明,为了等待该对象变为已通知状态,它将等待多长时间。(INFINITE为无限时间量,INFINITE已经定义为0xFFFFFFFF(或-1))

     4.3 windwos 多线程示例

 1 /////////////////////////////////////////////
 2 // 3 //\            windwos多线程练习
 4 //\            2017-05-26 cwp
 5 //\
 6 /////////////////////////////////////////////
 7 
 8 #include <stdio.h>
 9 #include <windows.h>
10 
11 // 线程函数
12 DWORD WINAPI ThreadFunc(LPVOID arg)
13 {
14     printf("thread id:%d, ThreadFunc\n", GetCurrentThreadId());
15     return NULL;
16 }
17 
18 int main()
19 {
20     printf("thread id:%d, man\n", GetCurrentThreadId());
21     HANDLE handle = CreateThread(NULL, 0, ThreadFunc, NULL, 0, NULL);
22     printf("Thread id:%d, Wait ThreadFunc exit\n", GetCurrentThreadId());
23     WaitForSingleObject(handle, INFINITE);
24     CloseHandle(handle);
25     return 0;
26 }

      4.4运行结果

      技术分享

5. linux多线程

    Linux系统内核只提供了轻量级进程的支持,并未实现线程模型。我们常用的LinuxThreads只是一个伪线程,是在用户级实现一个包括信号处理在内的线程管理机制。

    5.1 线程创建函数pthread_create

    

int pthread_create(pthread_t *thread, 
                            const pthread_attr_t *attr,
                            void *(*start_routine) (void *), 
                            void *arg);

参数说明:

  • thread:指向pthread_create类型的指针,用于引用新创建的线程。
  • attr:用于设置线程的属性,一般不需要特殊的属性,所以可以简单地设置为NULL。
  • start_routine:传递新线程所要执行的函数地址。
  • arg:新线程所要执行的函数的参数。

  返回值:

  调用如果成功,则返回值是0;如果失败则返回错误代码。

  每个线程都有自己的线程ID,以便在进程内区分。线程ID在pthread_create调用时回返给创建线程的调用者;一个线程也可以在创建后使用pthread_self()调用获取自己的线程ID.

      5.2 线程等待函数pthread_join

      

int pthread_join(pthread_t thread, void **retval);

参数说明:

  • thread:pthread_create类型的指针,等待该线程运行结束。
  • retval:线程的返回值。

  返回值:

  调用如果成功,则返回值是0;如果失败则返回错误代码。

      5.3 示例代码

       

 1 /////////////////////////////////////////////////////////
 2 // 3 //\        linux多线程示例
 4 //\        2017-05-25 cwp
 5 //\
 6 /////////////////////////////////////////////////////////
 7 
 8 #include <stdio.h>
 9 #include <stdlib.h>
10 #include <pthread.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <unistd.h>
14 
15 #include <sys/syscall.h>  
16 #define gettid() syscall(__NR_gettid) 
17 
18 // 线程1
19 void *ThreadFunc1(void *arg)
20 {
21     printf("Process id :%lu, Thread id : %lu, ThreadFunc1\n", getpid(), gettid());
22     return NULL;
23 }
24 
25 // 线程2
26 void *ThreadFunc2(void *arg)
27 {
28     printf("Process id :%lu, Thread id : %lu, ThreadFunc2\n", getpid(), gettid());
29     char *tmp = new char[strlen("ThreadFunc2") + 1];
30     memset(tmp, 0, 10);
31     sprintf(tmp, "ThreadFunc2");
32     return (void *)tmp;
33 }
34 
35 int main()
36 {
37     pthread_t id[2];
38     // 创建线程1
39     int ret = pthread_create(&id[0], NULL, ThreadFunc1, NULL);
40     if (ret != 0)
41     {
42     printf("Create thread1 failed!\n");
43     return 0;
44     }
45 
46     // 创建线程2
47     ret = pthread_create(&id[1], NULL, ThreadFunc2, NULL);
48     if (ret != 0)
49     {
50     printf("Create thread2 failed!\n");
51     return 0;
52     }
53 
54     // 等待线程1退出
55     pthread_join(id[0], NULL);
56 
57     // 等待线程2退出,并打印线程2的返回值
58     void *value =http://www.mamicode.com/ NULL;
59     pthread_join(id[1], &value);
60     printf("Process id :%lu, Thread id : %lu, man value : %s\n", getpid(), gettid(), (char *)value);
61     delete [] (char *)value;
62     
63     return 0;
64 }

      5.4 编译命令

      

g++ main.cpp -lpthread

      5.5 运行结果

cwp@linux-pg12:~/blog/thread> ./a.out 
Process id :5671, Thread id : 5672, ThreadFunc1
Process id :5671, Thread id : 5673, ThreadFunc2
Process id :5671, Thread id : 5671, man value : ThreadFunc2

 

注: 该博文同时在csdn更新(风逝_陈)

多线程