Linux多线程编程c++
线程概念编程
线程是指运行中的程序的调度单位。一个线程指的是进程中一个单一顺序的控制流,也被称为轻量级线程。它是系统独立调度和分配的基本单位。同一进程中的多个线程将共享该系统中的所有系统资源,好比文件描述符和信号处理等。一个进程能够有不少线程,每一个线程并行执行不一样的任务。服务器
线程与进程比较多线程
① 和进程相比,它是一种很是“节俭”的多任务操做方式。在Linux系统中,启动一个新的进程必须分配给它独立的地址空间,创建众多的数据表来维护其代码段、堆栈段和数据段,这种多任务工做方式的代价很是“昂贵”。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,并且线程间彼此切换所须要时间也远远小于进程间切换所须要的时间。架构
② 线程间方便的通讯机制。对不一样进程来讲它们具备独立的数据空间,要进行数据的传递只能经过通讯的方式进行。这种方式不只费时,并且很不方便。线程则否则,因为同一进程下的线程之间共享数据空间,因此一个线程的数据能够直接为其余线程所用,不只方便,并且快捷。函数
线程基本编程学习
Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,须要使用头文件pthread.h,链接时须要使用库libpthread.a。由于pthread的库不是Linux系统的库,因此在编译时要加上 -lpthread。例如:gcc filename -lpthread。注意,这里要讲的线程相关操做都是用户空间中的线程的操做。spa
线程建立:建立线程实际上就是肯定调用该线程函数的入口点,这里一般使用的函数是pthread_create()。在线程建立后,就开始运行相关的线程函数。线程
线程退出:在线程建立后,就开始运行相关的线程函数,在该函数运行完以后,该线程也就退出了,这也是线程退出的一种方法。另外一种退出线程的方法是使用函数pthread_exit(),这是线程的主动行为。这里要注意的是,在使用线程函数时,不能随意使用exit()退出函数来进行出错处理。因为exit()的做用是使调用进程终止,而一个进程每每包含多个线程,所以,在使用exit()以后,该进程中的全部线程都终止了。在线程中就可使用pthread_exit()来代替进程中的exit()。3d
线程等待:因为一个进程中的多个线程是共享数据段的,所以,一般在线程退出后,退出线程所占用的资源并不会随着线程的终止而获得释放。正如进程之间能够用wait()系统调用来同步终止并释放资源同样,线程之间也有相似机制,那就是pthread_join()函数。pthread_join()用于将当前进程挂起来等待线程的结束。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源就被收回。
线程取消:前面已经提到线程调用pthread_exit()函数主动终止自身线程,可是在不少线程应用中,常常会遇到在别的线程中要终止另外一个线程的问题,此时调用pthread_cancel()函数来实现这种功能,但在被取消的线程的内部须要调用pthread_setcancel()函数和pthread_setcanceltype()函数设置本身的取消状态。例如,被取消的线程接收到另外一个线程的取消请求以后,是接受函数忽略这个请求;若是是接受,则再判断马上采起终止操做仍是等待某个函数的调用等。
线程标识符获取:获取调用线程的标识ID。
线程清除:线程终止有两种状况:正常终止和非正常终止。线程主动调用pthread_exit()或者从线程函数中return都将使线程正常退出,这是可预见的退出方式;非正常终止是线程在其它线程的干预下,或者因为自身运行出错(好比访问非法地址)而退出,这种退出方式是不可预见的。不管是可预见的线程终止仍是异常终止,都回存在资源释放的问题,如何保证线程终止时能顺利地释放掉本身所占用的资源,是一个必须考虑的问题。
从pthread_cleanup_push()的调用点到pthread_cleanup_pop()之间的程序段中的终止动做(包括调用pthread_exit()和异常终止,不包括return)都将执行pthread_cleanup_push()所指定的清理函数。
Linuxc/c++服务器开发高阶视频学习资料+qun720209036获取
更多视频内容包括C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,MongoDB,ZK,流媒体,P2P,K8S,Docker,TCP/IP,协程,DPDK多个高级知识点分享。
视频连接:C/C++Linux服务器开发/后台架构师-学习视频
一、如何利用2个条件变量实现线程同步?
思路:就是来回的利用pthread_cond_signal()函数,当一方被阻塞时,唤醒函数能够唤醒pthread_cond_wait()函数,只不过pthread_cond_wait()这个方法要执行其后的语句,必须遇到下一个阻塞(也就是pthread_cond_wait()方法时),才执行唤醒后的其后语句。
代码以下:
pthread_mutex_lock(&mutex);
while(count <= MAX_NUM)
{
if(count%2 == 1){
printf("A = %dn", count);
count++;
pthread_cond_signal(&os);
sleep(5);
printf("bbbbbbbbbbbbbbbbbbbbbbbbbbbn");
}else{
printf("cccccccccccccccccccccccccccn");
pthread_cond_wait(&js, &mutex);
printf("dddddddddddddddddddddddddddn");
}
pthread_mutex_unlock(&mutex);
}}
void B(void arg)
{
pthread_mutex_lock(&mutex);
while(count <= MAX_NUM){
if(count%2 == 0){
printf("B = %dn", count);
count++;
pthread_cond_signal(&js);
}
else
{
pthread_cond_wait(&os, &mutex);
printf("aaaaaaaaaaaaaaaaaaaaaaaaaaaan");
}
}
pthread_mutex_unlock(&mutex);
}
int main(void)
{
pthread_t tid1, tid2;
pthread_create(&tid2, NULL, B, NULL);
sleep(1);
pthread_create(&tid1, NULL, A, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
运行结果
上面的这个程序就是:2个条件变量对一个互斥量的操做。signal()发送唤醒wait(),wait()以后的语句暂时不执行,直到下一次遇到wait()时,阻塞,返回执行唤醒的wait()以后的语句。
二、怎么建立10个线程的开始运行和结束过程?
利用2个条件变量和1个互斥量便可实现。
代码以下:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;void thread_fun1(void arg){
int i = (int )arg;
pthread_mutex_lock(&mutex);
printf("[%d] thread start upn", i);
pthread_cond_wait(&cond, &mutex);
printf("[%d]thread is wake upn", i);
pthread_mutex_unlock(&mutex);
}
void thread_fun2(void arg)
{
pthread_cond_broadcast(&cond); //广播,一次唤醒全部的线程}int main(void){
pthread_t tid1[10], tid2;
int i;
for(i = 0; i < 10; i++)
{
pthread_create(&tid1[i], NULL, thread_fun1, &i);//建立10个线程
sleep(1);
}
pthread_create(&tid2, NULL, thread_fun2, NULL);//建立1个线程
for(i = 0; i < 10; i++)
{ //主线程等子线程执行完
pthread_join(tid1[i], NULL);
}
pthread_join(tid2, NULL);
return 0;
}
运行结果
多线程的编程中:互斥量、条件变量是重中之重!!!