首页 > 代码库 > 多线程
多线程
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更新(风逝_陈)
多线程