文章目录
#线程
线程是为了解决需要做多个任务而发明的。
在之前是通过进程解决的。
但是使用多个进程进行并发是有缺点的:
*一个进程的创建与销毁是需要消耗很多资源的。
- 进程之间相互独立,进程间通信的手段,比较复杂
所以,线程就发明了出来。
线程的特点:
*一个进程可以有许多个线程
*一个线程只能有一个进程
*一个进程里面的线程,会共享进程的各项资源(内存,文件描述符)
*与函数调用有关的栈帧,是不会共享的。是会随着线程的切换而切换的。
在Linux下使用pthread_create来创建线程。
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Compile and link with -pthread.
那么具体的是什么意思呢?
我们下面进行一一的解释:
参数说明
- thread: 是一个传出参数,表示的是线程ID
- attr:线程的属性设置,是可以为NULL的。
- start_routine:新线程开始执行的函数。
- arg:是新线程执行函数的实际参数。
以下是一个具体的例子。
我们可以得到看到
这样一个简单的新的线程就创建完了。
#关于线程怎么退出
一个线程一旦启动了,是可以退出的,以下就是几种线程会退出的情况:
- 当进程结束的时候(或者是main中的主线程推出的时候)
- 线程函数(start_routine)达到返回
- 线程自己调用了pthread_exit线程退出函数
#线程等待
调用pthread_join可以等待线程:
得到的效果就是:
我们得到的效果就是,新线程就会先执行,然后main里面的会等到新的线程结束之后再开始执行。
如果我们创建了一个线程,一开始就不想等,就可以在该线程当中使用pthread_detach方法,将该线程的属性修改为detach
##线程的同步问题
我们先来看看以下的代码:
理论的g_Count应该是400000的,但是实际的情况并不会每次都是400000,这就是因为线程没有同步导致的。
我们可以看看具体的原因:
在C++当中,一个语句:g_nCount++;编译的时候会将一条语句转化为多条的汇编语句:
例如:
g_nCount++:
转化为:
mov eax,[g_nCount]//将g_nCount放进寄存器里面
add eax,0x1//寄存器加1
mov [g_nCount],eax//将g_nCount从寄存器里面提取出来。
正常的情况下,我们可以期望的是程序运行是以下的效果:
线程1的一个语句结束后,时间片再切换到线程2。但是实际上CPU的时间片的切换并不都是这样的。
我们有时候会出现以下的类似情况
结果与原来的就会有所差别。
这就是线程不同步导致的BUG。
具体的解决方法我们会在下次的笔记当中进行简单介绍。