做微网站的公司,个人网站 百度收录,网站开发运营成本,评论凡科网站建设怎么样目录
0.前言 1.pthread库
2.关于控制线程的接口
2.1.创建线程#xff08;pthread_create#xff09;
2.2.线程等待#xff08;pthread_join#xff09;
代码示例1#xff1a;
编辑
***一些问题***
2. 3.创建多线程
3.线程的终止 #xff08;pthread_exit /…目录
0.前言 1.pthread库
2.关于控制线程的接口
2.1.创建线程pthread_create
2.2.线程等待pthread_join
代码示例1
编辑
***一些问题***
2. 3.创建多线程
3.线程的终止 pthread_exit / pthread_cancel
总结
4.线程分离 pthread_detach
新线程分离主线程
5.C 11中的多线程 0.前言 线程的创建终止等待分离 1.pthread库 Linux中有线程吗没有只有轻量级进程--就是线程。因此Linux下的系统调用只会给用户提供创建轻量级进程的接口这些接口需要被pthread库进行封装按照线程的接口提供给用户用户通过这些接口来创建终止等待分离线程。所以我们称Linux的线程为用户级线程windows的线程为内核级线程。 2.关于控制线程的接口 2.1.创建线程pthread_create 引入接口pthread_create用于创建一个新线程 参数说明 pthread_t *thread这是一个指向 pthread_t 类型的指针用于存储新创建的线程的标识符。通过这个标识符你可以引用或操作这个线程。const pthread_attr_t *attr这是一个指向 pthread_attr_t 类型的指针用于设置线程的属性如堆栈大小、调度策略等。如果传递 NULL则使用默认属性。void *(*start_routine) (void *)这是新线程将要执行的函数的指针。该函数必须接受一个 void * 类型的参数并返回一个 void * 类型的值。这个函数的参数 arg 将被传递给新线程。输入一个函数的地址void *arg这是传递给 start_routine 函数的参数。 如果成功pthread_create 返回 0如果失败则返回错误码。 2.2.线程等待pthread_join 引入接口pthread_join 参数说明 pthread_t thread这是要等待的线程的标识符ID该标识符是由 pthread_create 函数返回的。void **retval这是一个指向 void * 指针的指针用于接收被等待线程的返回值。如果被等待的线程调用了 pthread_exit 并传递了一个返回值或者简单地返回了一个值对于从 void* 返回类型的线程函数那么这个值就可以通过这个参数返回给等待的线程。如果对这个返回值不感兴趣可以传递 NULL。 如果成功pthread_join 返回 0如果失败则返回错误码。 代码示例1 线程的创建和等待 #include iostream
#include string
#include pthread.h
#include unistd.hvoid *threadrun(void *args)
{int cnt 10;while(cnt){std::coutnew thread run ...,cnt: cnt--std::endl;sleep(1);}return nullptr;
}
int main()
{pthread_t tid;int n pthread_create(tid,nullptr,threadrun,(void*)thread 1);std::coutmain thread join begin...std::endl;n pthread_join(tid,nullptr);if(n0){std::coutmain thread wait successstd::endl;}return 0;
} ***一些问题*** 问题1mian和new线程谁先运行不确定 问题2我们期望谁最后退出main thread如何来保证呢 join来保证不join呢会造成类似僵尸进程的问题 问题3tid是什么样子的 代码以16进制的形式打印出来 std::string PrintToHex(pthread_t tid)
{char buffer[64];snprintf(buffer, sizeof(buffer), 0x%lx, tid);return buffer;
}std::string tid_str PrintToHex(tid); // 我们按照16进行打印出来std::cout tid : tid_str std::endl; 这个线程id是一个虚拟地址后面再谈 问题4全面看待线程函数传参它可以传任意类型当然也可以传类对象的地址,这意味着我们可以给线程传递多个参数多种方法了 class ThreadData
{
public:std::string name;int num;
};
void *threadrun(void *args)
{//静态强转 ThreadData *td static_castThreadData*(args);int cnt 10;while(cnt){std::cout td-name run ... num is: td-num , cnt: cnt-- std::endl;sleep(1);}return nullptr;
}
int main()
{ThreadData *tdnew ThreadData();td-name thread-1;td-num 1;int n pthread_create(tid,nullptr,threadrun,(void*)td);
} 传类对象的时候最好是在堆上开辟这样多个线程之间就不会互相干扰。 问题5pthread_create第三个参数的返回值该返回值是void*类型的如果主线程想要获取线程的返回值可以通过join函数获取在线程没出错的情况下是能获取到的如果某一个线程出错主线程也是会跟着崩掉因为线程出错误是直接给整个进程发信号的导致整个进程都挂掉了 代码示例返回一个类对象 #include iostream
#include string
#include thread
#include stdlib.h
#include pthread.h
#include unistd.hclass ThreadData
{
public:int Excute(){return x y;}
public:std::string name;int x;int y;// other
};class ThreadResult
{
public:std::string print(){return std::to_string(x) std::to_string(y) std::to_string(result);}
public:int x;int y;int result;
};
std::string PrintToHex(pthread_t tid)
{char buffer[64];snprintf(buffer, sizeof(buffer), 0x%lx, tid);return buffer;
}
void *threadRun(void *args)
{ThreadData *td static_castThreadData*(args); // (ThreadData*)argsThreadResult *result new ThreadResult();int cnt 10;while(cnt){sleep(3); std::cout td-name run ... , cnt: cnt-- std::endl;result-result td-Excute();result-x td-x;result-y td-y;break;//跑一次退出}delete td;return (void*)result;
}
int main()
{pthread_t tid;ThreadData *tdnew ThreadData();td-namethread-1;td-x10;td-y20;int n pthread_create(tid, nullptr, threadRun, td);std::string tid_str PrintToHex(tid); // 我们按照16进行打印出来std::cout tid : tid_str std::endl;std::coutmain thread join begin...std::endl;ThreadResult *result nullptr; // 开辟了空间的n pthread_join(tid, (void**)result); if(n 0){std::cout main thread wait success, new thread exit code: result-print() std::endl;}sleep(10);return 0;
} 2. 3.创建多线程 下面是一段示例 初步创建线程id和线程name保存所有线程的id信息最后主线程回收每个线程 #include iostream
#include string
#include vector
#include thread
#include stdlib.h
#include pthread.h
#include unistd.hconst int num 10;
std::string PrintToHex(pthread_t tid)
{char buffer[64];snprintf(buffer, sizeof(buffer), 0x%lx, tid);return buffer;
}void *threadrun(void *args)
{std::string name static_castconst char*(args);while(true){std::cout name is running std::endl;sleep(1);break;}return args;
}
int main()
{std::vectorpthread_t tids;for(int i 0; i num; i){// 1. 有线程的idpthread_t tid;// 2. 线程的名字char *name new char[128];snprintf(name, 128, thread-%d, i1);pthread_create(tid, nullptr, threadrun, /*线程的名字*/name);//3.保存所有线程idtids.push_back(tid);}for(auto tid:tids){void*namenullptr;pthread_join(tid,name);std::cout(const char*)namequit...std::endl;delete (const char*)name;}}
我们用vector储存线程id集 3.线程的终止 pthread_exit / pthread_cancel 对于新线程来说线程终止函数returnmain函数结束主线程结束表示整个进程结束 关于exit专门用来终止进程的不能用来终止线程任意一个线程调用exit都表示进程终止如果你想让一个线程马上终止这里就要用到第三个接口pthread_exit 参数 retval这是一个指向任意数据的指针该数据将被线程的终止状态所使用并且可以被其他线程通过调用 pthread_join 来访问。 当然你还可以使用接口pthread_cancel取消一个线程 参数 thread要发送取消请求的线程标识符pthread_t 类型。 代码示例 #include iostream
#include string
#include vector
#include thread
#include stdlib.h
#include pthread.h
#include unistd.hconst int num 10;
std::string PrintToHex(pthread_t tid)
{char buffer[64];snprintf(buffer, sizeof(buffer), 0x%lx, tid);return buffer;
}void *threadrun(void *args)
{std::string name static_castconst char*(args);while(true){std::cout name is running std::endl;sleep(1);break;}//return args;pthread_exit(args);
}
int main()
{std::vectorpthread_t tids;for(int i 0; i num; i){// 1. 有线程的idpthread_t tid;// 2. 线程的名字char *name new char[128];snprintf(name, 128, thread-%d, i1);pthread_create(tid, nullptr, threadrun, /*线程的名字*/name);//3.保存所有线程idtids.push_back(tid);}for(auto tid:tids){void*namenullptr;pthread_join(tid,name);std::cout(const char*)namequit...std::endl;delete (const char*)name;}sleep(100);
} 在主线程未退出的情况下其它线程成功退出了。 线程取消退出结果为-1 #define PTHREAD_CANCELED ((void *) -1) #include iostream
#include string
#include vector
#include thread
#include stdlib.h
#include pthread.h
#include unistd.hconst int num 10;
std::string PrintToHex(pthread_t tid)
{char buffer[64];snprintf(buffer, sizeof(buffer), 0x%lx, tid);return buffer;
}void *threadrun(void *args)
{std::string name static_castconst char*(args);while(true){std::cout name is running std::endl;sleep(1);}
}
int main()
{std::vectorpthread_t tids;for(int i 0; i num; i){// 1. 有线程的idpthread_t tid;// 2. 线程的名字char *name new char[128];snprintf(name, 128, thread-%d, i1);pthread_create(tid, nullptr, threadrun, /*线程的名字*/name);//3.保存所有线程idtids.push_back(tid);}sleep(5);for(auto tid : tids){pthread_cancel(tid); // 取消std::cout cancel: PrintToHex(tid) std::endl;void *result nullptr; // 线程被取消线程的退出结果是-1 #define PTHREAD_CANCELED ((void *) -1)pthread_join(tid, result);std::cout (long long int)result quit... std::endl;}sleep(100);
} 总结 新线程如何终止 1. 线程函数 return 2. pthread_exit 3. main thread call pthread_cancel, 新线程退出结果是-1 4.线程分离 pthread_detach 线程分离的是将线程与创建它的进程或主线程的终止状态分离。当一个线程被分离后它依然属于进程内部但它不再需要被其他线程显式地等待通过 pthread_join来释放其资源。当分离的线程终止时它的所有资源会自动被释放回系统无需其他线程的干预。 参数 thread要分离的线程的标识符pthread_t 类型。 返回值 成功时返回 0。失败时返回错误号。 一个线程被创建默认是joinable必须要被join的如果一个线程被分离线程的工作状态分离状态不需要/不能被join的。 这里我们还需要借助一个接口pthread_self一调用就是获取自己的线程id 新线程分离主线程 代码示例一旦分离主线程就不能等待了如果等待会发生什么这里我们看一下分离且join后join的返回值 我们发现返回值为22这说明主线程以等待就直接出错了。所以主线程无需等待主线程可以做自己的事情了。如果在线程分离的情况下且主线程没有做等待新线程出错了整个进程也是直接挂掉的因为它还是在进程内部。 #include iostream
#include string
#include vector
#include thread
#include stdlib.h
#include pthread.h
#include unistd.hconst int num 10;
std::string PrintToHex(pthread_t tid)
{char buffer[64];snprintf(buffer, sizeof(buffer), 0x%lx, tid);return buffer;
}void *threadrun(void *args)
{pthread_detach(pthread_self());std::string name static_castconst char*(args);while(true){std::cout name is running std::endl;sleep(1);}pthread_exit(args);
}
int main()
{std::vectorpthread_t tids;for(int i 0; i num; i){// 1. 有线程的idpthread_t tid;// 2. 线程的名字char *name new char[128];snprintf(name, 128, thread-%d, i1);pthread_create(tid, nullptr, threadrun, /*线程的名字*/name);//3.保存所有线程idtids.push_back(tid);}sleep(5);for(auto tid : tids){std::cout cancel: PrintToHex(tid) std::endl;void *result nullptr; // 线程被取消线程的退出结果是-1 #define PTHREAD_CANCELED ((void *) -1)int n pthread_join(tid, result);std::cout (long long int)result quit...n : n std::endl;}sleep(100);
} 5.C 11中的多线程 C11在Linux中使用多线程编译时也是要链接pthread库因为C11中的多线程本质就是对原生线程库接口的封装 #include iostream
#include string
#include vector
#include thread
#include stdlib.h
#include pthread.h
#include unistd.hvoid threadrun(std::string name, int num)
{while(num){std::cout name num : num std::endl;num--;sleep(1);}
}int main()
{std::string name thread-1;std::thread mythread(threadrun, std::move(name), 10);while(true){std::cout main thhread... std::endl;sleep(1);}mythread.join();return 0;
}