(1)响应速度更灵敏
多个任务不同线程执行,各自占用一段CPU时机,看起来任务同时进行,界面及时更新。
(2)运行效率更高
充分发挥cpu内核性能,增加运行效率。
(3)通信更高效
线程共享进程地址空间,比进程通信更高效和方便。
(4)开销更小
线程创建、切换等系统开销比进程更小。
操作系统分类:
(1)单进程、单线程,MS-DOS。
(2)多进程、单线程,多数UNIX(及类UNIX的Linux)。
(3)多进程、多线程,Win32(Windows NT/2000/XP/7/8/10等)、Solaris 2.x、OS/2。
(4)单进程、多线程,VxWorks。
CPU执行的是线程,线程是程序的最小执行单位,是操作系统分配CPU时间的最小实体。
线程共享进程的公共资源,如虚拟地址空间、全局变量等,线程可有自己私有资源,如堆栈、堆栈中定义的静态变量和动态变量、CPU寄存器的状态等(程序计数器、一组寄存器和线程栈,线程栈用于维护线程在执行代码时所需要的所有函数参数和局部变量)。
线程好处:
(1)线程创建、终止比进程更快;
(2)线程(尤其用户级)比进程切换更快;
(3)线程可以解决父子进程模型中子进程必须复制父进程地址空间的问题;
(4)线程对解决客户/服务器模型非常有效。
使用多线程情况:
(1)各任务相对独立;
(2)某些任务耗时较多;
(3)各任务有不同优先级;
(4)一些实时系统应用。
(1)就绪态
运行条件满足,等待处理器调度(调度策略)。等待原因:线程刚创建(刚创建线程不一定马上运行,一般先就绪)、刚重阻塞态恢复、其它线程抢占。
(2)运行态
占用着处理器运行。
(3)阻塞态
等待处理器之外的其它条件(I/O操作、互斥锁释放、条件变量的改变等)而无法运行的状态。
(4)终止态
线程函数运行结束或被其它线程取消。此时线程结束,但占用资源还未被回收,可以被重新复活。
线程创建后进入运行态要执行的函数。
全局函数或类的静态函数。
void *ThreadProc(void *arg);
句柄标识线程对象,ID标识线程本身。
POSIX多线程API函数,传统;
C++自带线程类,新。
API函数 | 含义 |
---|---|
pthread_create | 创建线程 |
pthread_exit | 终止自身线程 |
pthread_join | 等待线程结束 |
pthread_self | 线程ID |
pthread_cancel | 取消其它线程 |
pthread_kill | 线程发送信号 |
int pthread_create(pthread_t *pid, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
pid指向线程ID,pthread_t是unsigned long int;
pthread_attr_t,线程属性结构,NULL使用默认属性;
start_routine指向线程函数地址;
arg指向传给线程函数的参数;
成功返回0。
int pthread_join(pthread_t pid, void **value_ptr);
pid,线程ID;
value_ptr,获取线程退出值,可为NULL;
成功返回0。
pthread_join阻塞函数,让主线程挂起(即休眠,让出CPU),直到子线程退出,同时释放子线程所占资源。子线程退出后,主线程会收到系统信号,从休眠中恢复。
gcc -o test test.cpp -lpthread
#include
#include
#include //sleep
void *thfunc(void *arg)
{
printf("in thfunc\n");
return (void *)0;
}
int main(int argc, char *argv[])
{
pthread_t tidp;
int ret = pthread_create(&tidp, NULL, thfunc, NULL);
if (ret)
{
printf("pthread_create failed: %d\n", ret);
return -1;
}
sleep(1);
printf("in main:thread is created\n");
return 0;
}
#include
#include
void *thfunc(void *arg)
{
int n = *(int *)(arg);
printf("in thfunc: n=%d\n", n);
return (void *)0;
}
int main(int argc, char *argv[])
{
pthread_t tidp;
int n = 110;
int ret = pthread_create(&tidp, NULL, thfunc, &n);
if (ret)
{
printf("pthread_create failed: %d\n", ret);
return -1;
}
pthread_join(tidp, NULL);
printf("in main:thread is created\n");
return 0;
}
#include
#include
void *thfunc(void *arg)
{
char *str = (char *)arg;
printf("in thfunc: str=%s\n", str);
return (void *)0;
}
int main(int argc, char *argv[])
{
pthread_t tidp;
const char *str = "hello world";
int ret = pthread_create(&tidp, NULL, thfunc, (void *)str);
if (ret)
{
printf("pthread_create failed: %d\n", ret);
return -1;
}
pthread_join(tidp, NULL);
printf("in main:thread is created\n");
return 0;
}
#include
#include
typedef struct
{
int n;
const char *str;
} MYSTRUCT;
void *thfunc(void *arg)
{
MYSTRUCT *p = (MYSTRUCT *)arg;
printf("in thfunc: n=%d, str=%s\n", p->n, p->str);
return (void *)0;
}
int main(int argc, char *argv[])
{
pthread_t tidp;
MYSTRUCT mystruct{110, "hello world"};
int ret = pthread_create(&tidp, NULL, thfunc, (void *)&mystruct);
if (ret)
{
printf("pthread_create failed:%d\n", ret);
return -1;
}
pthread_join(tidp, NULL);
printf("in main:thread is created\n");
return 0;
}
#include
#include
int gn = 10;
void *thfunc(void *arg)
{
gn++;
printf("in thfunc: gn=%d,\n", gn);
return (void *)0;
}
int main(int argc, char *argv[])
{
pthread_t tidp;
int ret = pthread_create(&tidp, NULL, thfunc, NULL);
if (ret)
{
printf("pthread_create failed:%d\n", ret);
return -1;
}
pthread_join(tidp, NULL);
gn++;
printf("in main: gn=%d\n", gn);
return 0;
}
分离状态(Detached State)、调度策略和参数(Scheduling Policy and Parameters)、作用域(Scope)、栈尺寸(Stack Size)、栈地址(Stack Address)、优先级(Priority)等。
union pthread_attr_t {
char __size[__SIZEOF_PTHREAD_ATTR_T];
long int __align;
};
#define _GNU_SOURCE
#include
int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr);
//获取线程属性,成功0。
默认线程属性,非分离、堆栈大小1MB,与父进程同样优先级。
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
线程终止方式,默认可连接。
非分离状态(可连接,joinable, PTHREAD_CREATE_JOINABLE),可以被其它线程收回资源和取消,不会主动释放资源(比如栈空间,僵尸线程),必须等待其它线程回收资源(pthread_join)。线程函数结束(return或pthread_exit)时,都不会释放线程占用的堆栈和线程描述符(8KB多)。父进程先于子线程退出,不会泄漏资源,会被init进程收养。线程不能被多个线程等待,第一个收到信号的线程成功返回,其余调用pthread_join的线程得到错误代码ESRCH。
可分离线程能独立(分离)出去,运行结束时,其资源立刻被系统回收。两种方式设置,pthread_detach和pthread_attr_setdetachstate(pthread_attr_t *attr, PTHREAD_CREATE_DETACHED)。
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
//PTHREAD_CREATE_DETACHED或PTHREAD_CREATE_JOINABLE
//设置线程分离状态属性。
#include
#include
#include
#include
using namespace std;
void *thfunc(void *arg)
{
sleep(1);
cout << ("sub thread is running\n");
ofstream("tmp.file") << "out\n";
//exit(5);
return NULL;
}
int main(int argc, char *argv[])
{
pthread_attr_t thread_attr;
int res = pthread_attr_init(&thread_attr);
if (res)
cout << "pthread_attr_init failed:" << res << endl;
res = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
if (res)
cout << "pthread_attr_setdetachstate failed:" << res << endl;
pthread_t thread_id;
res = pthread_create(&thread_id, &thread_attr, thfunc, NULL);
if (res)
cout << "pthread_create failed:" << res << endl;
cout << "main thread will exit\n";
pthread_attr_destroy(&thread_attr);
pthread_exit(NULL);
//return 0;
}
#include
#include
using namespace std;
void *thfunc(void *arg)
{
cout << ("sub thread is running\n");
return NULL;
}
int main(int argc, char *argv[])
{
pthread_attr_t thread_attr;
int res = pthread_attr_init(&thread_attr);
if (res)
cout << "pthread_attr_init failed:" << res << endl;
res = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
if (res)
cout << "pthread_attr_setdetachstate failed:" << res << endl;
pthread_t thread_id;
res = pthread_create(&thread_id, &thread_attr, thfunc, NULL);
if (res)
cout << "pthread_create failed:" << res << endl;
cout << "main thread will exit\n";
pthread_attr_destroy(&thread_attr);
pthread_exit(NULL);//主线程退出,进程不会退出,下面语句不会再执行。
//进程资源会为其它线程保持打开,直到其它线程都终止。
cout << "main thread has exited, this line will not run\n";
return 0;
}
int pthread_detach(pthread_t thread);
//可连接线程转变为可分离线程(退出或pthread_exit后系统回收资源)
//EINVAL,非可连接线程
//ESRCH,线程未找到
//pthread_join后pthread_detach线程无作用
//pthread_detach后pthread_join出错
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
//获取分离状态
#ifndef _GNU_SOURCE
#define _GNU_SOURCE //pthread_getattr_np
#endif
#include
#include
#include
#include
#include
#define handle_error_en(en, msg) \
do \
{ \
errno = en; \
perror(msg); \
exit(EXIT_FAILURE); \
} while (0)
static void *thread_start(void *arg)
{
pthread_attr_t gattr;
int s = pthread_getattr_np(pthread_self(), &gattr);
if (s != 0)
handle_error_en(s, "pthread_getattr_np");
printf("Thread's detachstate attributes:\n");
int i;
s = pthread_attr_getdetachstate(&gattr, &i);
if (s)
handle_error_en(s, "pthread_attr_getdetachstate");
printf("Detach state = %s\n",
(i == PTHREAD_CREATE_DETACHED) ? "PTHREAD_CREATE_DETACHED" : (i == PTHREAD_CREATE_JOINABLE) ? "PTHREAD_CREATE_JOINABLE"
: "???");
pthread_attr_destroy(&gattr);
return 0;
}
int main(int argc, char *argv[])
{
pthread_t thr;
int s = pthread_create(&thr, NULL, &thread_start, NULL);
if (s != 0)
{
handle_error_en(s, "pthread_create");
return 0;
}
pthread_join(thr, NULL);
return 0;
}
#ifndef _GNU_SOURCE
#define _GNU_SOURCE //pthread_getattr_np
#endif
#include
#include
#include
#include
#include
static void *thread_start(void *arg)
{
pthread_attr_t gattr;
int s = pthread_getattr_np(pthread_self(), &gattr);
if (s != 0)
printf("pthread_getattr_np failed\n");
int i;
s = pthread_attr_getdetachstate(&gattr, &i);
if (s)
printf("pthread_attr_getdetachstate failed");
printf("Detach state = %s\n",
(i == PTHREAD_CREATE_DETACHED) ? "PTHREAD_CREATE_DETACHED" : (i == PTHREAD_CREATE_JOINABLE) ? "PTHREAD_CREATE_JOINABLE"
: "???");
pthread_detach(pthread_self());
s = pthread_getattr_np(pthread_self(), &gattr);
if (s != 0)
printf("pthread_getattr_np failed\n");
s = pthread_attr_getdetachstate(&gattr, &i);
if (s)
printf(" pthread_attr_getdetachstate failed");
printf("after pthread_detach, \nDetach state = %s\n",
(i == PTHREAD_CREATE_DETACHED) ? "PTHREAD_CREATE_DETACHED" : (i == PTHREAD_CREATE_JOINABLE) ? "PTHREAD_CREATE_JOINABLE"
: "???");
pthread_attr_destroy(&gattr);
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t thread_id;
int s = pthread_create(&thread_id, NULL, &thread_start, NULL);
if (s != 0)
{
printf("pthread_create failed\n");
return 0;
}
pthread_exit(NULL);
}
int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);
//获取栈尺寸(字节)
#ifndef _GNU_SOURCE
#define _GNU_SOURCE // pthread_getattr_np()
#endif
#include
#include
#include
#include
#include
#include
static void *thread_start(void *arg)
{
pthread_attr_t gattr;
int res = pthread_getattr_np(pthread_self(), &gattr);
if (res)
printf("pthread_getattr_np failed\n");
size_t stack_size;
res = pthread_attr_getstacksize(&gattr, &stack_size);
if (res)
printf("pthread_getattr_np failed\n");
printf("Default stack size is %lu byte; minimum is %lu byte\n", stack_size, PTHREAD_STACK_MIN);
pthread_attr_destroy(&gattr);
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t thread_id;
int s = pthread_create(&thread_id, NULL, &thread_start, NULL);
if (s != 0)
{
printf("pthread_create failed\n");
return 0;
}
pthread_join(thread_id, NULL);
return 0;
}
线程分实时和分时。线程调度策略:
(1)SCHED_OTHER
分时调度策略(轮转策略),默认,非实时。线程分配时间片,无优先级,按序运行。
(2)SCHED_FIFO
先来先服务调度策略,实时,支持优先级抢占。按序运行,直到更高优先级任务抢占。优先级范围1~99。
(3)SCHED_RR
时间片轮转(轮询)调度策略,实时,支持优先级抢占。线程分配特定时间片,用完后重新分配,保证相同优先级线程能够公平地调度。优先级范围1~99。
int sched_get_priority_min(int policty);
int sched_get_priority_max(int policty);
//SCHED_FIFO、SCHED_RR、SCHED_OTHER
#include
#include
#include
int main()
{
printf("Valid priority range for SCHED_OTHER: %d - %d\n",
sched_get_priority_min(SCHED_OTHER),
sched_get_priority_max(SCHED_OTHER));
printf("Valid priority range for SCHED_FIFO: %d - %d\n",
sched_get_priority_min(SCHED_FIFO),
sched_get_priority_max(SCHED_FIFO));
printf("Valid priority range for SCHED_RR: %d - %d\n",
sched_get_priority_min(SCHED_RR),
sched_get_priority_max(SCHED_RR));
return 0;
}
线程结束方法:
(1)线程函数中调用pthread_exit;
不会导致C++对象被析构,可放心使用。
(2)线程所属进程结束,比如进程调用exit;
最好不用,线程函数中C++对象不会被销毁。
(3)线程函数执行结束,return;
最安全方式。
(4)线程被其它线程通知结束或取消。
中途停止线程,发送取消信号。
主线程中调用pthread_exit(NULL);将结束主线程,但进程不会立即退出。
#include
#include
#include
#include
#include
#define PTHREAD_NUM 2
void *thrfunc1(void *arg)
{
static int count = 1;
pthread_exit((void *)(&count));
}
void *thrfunc2(void *arg)
{
static int count = 2;
return (void *)(&count);
}
int main(int argc, char *argv[])
{
pthread_t pid[PTHREAD_NUM];
if (pthread_create(&pid[0], NULL, thrfunc1, NULL) != 0)
{
perror("create pid first failed");
return -1;
}
if (pthread_create(&pid[1], NULL, thrfunc2, NULL))
{
perror("create pid second failed");
return -1;
}
int *pRet1;
if (pid[0] != 0)
{
pthread_join(pid[0], (void **)&pRet1);
printf("get thread 0 exitcode: %d\n", *pRet1);
}
int *pRet2;
if (pid[1] != 0)
{
pthread_join(pid[1], (void **)&pRet2);
printf("get thread 1 exitcode: %d\n", *pRet2);
}
return 0;
}
int pthread_kill(pthread_t threadId, int signal);
//signal等于0用于探测线程是否存在
//ESRCH,线程不存在
//EINVAL,信号不合法
sigaction注册信号处理函数,默认会退出进程。
#include
#include
#include
#include //sleep
using namespace std;
static void on_signal_term(int sig)
{
cout << "sub thread will exit" << endl;
pthread_exit(NULL);
}
void *thfunc(void *arg)
{
signal(SIGQUIT, on_signal_term);
int tm = 50;
while (true)
{
cout << "thrfunc--left:" << tm << " s--" << endl;
sleep(1);
tm--;
}
return (void *)0;
}
int main(int argc, char *argv[])
{
pthread_t pid;
int res = pthread_create(&pid, NULL, thfunc, NULL);
sleep(5);
pthread_kill(pid, SIGQUIT);
pthread_join(pid, NULL);
cout << "sub thread has completed, main thread will exit\n";
return 0;
}
#include
#include
#include
#include //sleep
#include "errno.h"
using namespace std;
void *thfunc(void *arg)
{
int tm = 50;
while (1)
//while (tm > 48)
{
cout << "thrfunc--left:" << tm << " s--" << endl;
sleep(1);
tm--;
}
return (void *)0;
}
int main(int argc, char *argv[])
{
pthread_t pid;
int res = pthread_create(&pid, NULL, thfunc, NULL);
sleep(5);
int kill_rc = pthread_kill(pid, 0);
cout << kill_rc << endl;
if (kill_rc == ESRCH)
cout << "the specified thread did not exists or already quit\n";
else if (kill_rc == EINVAL)
cout << "signal is invalid\n";
else
cout << "the specified thread is alive\n";
return 0;
}
pthread_cancel发送终止线程运行的请求,不一定成功。
发送终止线程运行的请求成功,系统并不会马上关闭被取消的线程,只有被取消的线程下次调用一些系统函数或C库函数(比如printf)或pthread_testcancel(死循环中,让内核有机会去检测是否需要取消当前线程)时,才会真正结束线程。被取消线程成功停止运行时,会返回常数PTHREAD_CANCELED(-1)。线程执行过程中,检测是否有未响应取消信号的地方,叫取消点,位于printf、pthread_testcancel、read/write、sleep等函数调用的地方。
#include
#include
#include
#include //sleep
void *thfunc(void *arg)
{
printf("thread start-------- \n");
int i=1;
while(1)
i++;
return (void *)0;
}
int main()
{
pthread_t tid;
pthread_create(&tid, NULL, thfunc, NULL);
sleep(1);
pthread_cancel(tid);
int *ret = NULL;
pthread_join(tid, (void **)&ret);
if (ret == PTHREAD_CANCELED)
printf("thread has stopped,and exit code: -1\n"); //*ret,error
else
printf("some error occured");
return 0;
}
#include
#include
#include
#include //sleep
void *thfunc(void *arg)
{
printf("thread start-------- \n");
int i=1;
while(1){
i++;
pthread_testcancel();
}
return (void *)0;
}
int main()
{
pthread_t tid;
pthread_create(&tid, NULL, thfunc, NULL);
sleep(1);
pthread_cancel(tid);
int *ret = NULL;
pthread_join(tid, (void **)&ret);
if (ret == PTHREAD_CANCELED)
printf("thread has stopped,and exit code: -1\n");//*ret,error
else
printf("some error occured");
return 0;
}
需要线程退出时执行清理的机会,保证顺利地释放掉占用的资源,尤其是锁。
void pthread_cleanup_push(void (*routine)(void *), void *arg);
//压入清理函数routine。
/*
清理函数routine执行情况:
(1)线程主动结束,return或ptherad_exit
(2)pthread_cleanup_pop(1)
(3)其它线程函数调用pthread_cancel
*/
void pthread_cleanup_pop(int execute);
//弹出栈顶清理函数的同时,是否执行清理函数。
//0不执行,非0执行。
pthread_cleanup_push和pthread_cleanup_pop必须成对出现,否则语法错误。
void *thread1(void *arg){
pthread_cleanup_push(clean_funnc, ...);
pthread_mutex_lock(&mutex);
sock = accept(...);
pthread_mutex_unlock(&mutex);
pthread_cleanup_pop(0);
return NULL;
}
#include
#include
#include
#include //strerror
void mycleanfunc(void *arg)
{
printf("mycleanfunc: %d\n", *((int *)arg));
}
void *thfrunc1(void *arg)
{
int m = 1;
printf("thfrunc1 comes \n");
pthread_cleanup_push(mycleanfunc, &m);
pthread_cleanup_pop(0);
return (void *)0;//return 不会执行
}
void *thfrunc2(void *arg)
{
int m = 2;
printf("thfrunc2 comes \n");
pthread_cleanup_push(mycleanfunc, &m);
pthread_exit((void *)0);
pthread_cleanup_pop(0);
}
int main(void)
{
pthread_t pid1;
int res = pthread_create(&pid1, NULL, thfrunc1, NULL);
if (res)
{
printf("pthread_create failed: %s\n", strerror(res));
exit(1);
}
pthread_join(pid1, NULL);
pthread_t pid2;
res = pthread_create(&pid2, NULL, thfrunc2, NULL);
if (res)
{
printf("pthread_create failed: %s\n", strerror(res));
exit(1);
}
pthread_join(pid2, NULL);
printf("main over\n");
return 0;
}
#include
#include
#include
#include //strerror
void mycleanfunc(void *arg)
{
printf("mycleanfunc: %d\n", *((int *)arg));
}
void *thfrunc1(void *arg)
{
int m=1, n=2;
printf("thfrunc1 comes \n");
pthread_cleanup_push(mycleanfunc, &m);
pthread_cleanup_push(mycleanfunc, &n);
pthread_cleanup_pop(1);
pthread_exit(0);
pthread_cleanup_pop(0);
}
int main(void)
{
pthread_t pid1 ;
int res = pthread_create(&pid1, NULL, thfrunc1, NULL);
if (res)
{
printf("pthread_create failed: %s\n", strerror(res));
exit(1);
}
pthread_join(pid1, NULL);
printf("main over\n");
return 0;
}
#include
#include
#include
#include //sleep
void mycleanfunc(void *arg)
{
printf("mycleanfunc: %d\n", *((int *)arg));
}
void *thfunc(void *arg)
{
int i = 1;
printf("thread start-------- \n");
pthread_cleanup_push(mycleanfunc, &i);
while (1)
{
i++;
printf("i=%d\n", i);
}
printf("this line will not run\n");
pthread_cleanup_pop(0);
return (void *)0;
}
int main()
{
pthread_t tid;
pthread_create(&tid, NULL, thfunc, NULL);
sleep(1);
pthread_cancel(tid);
int *ret = NULL;
pthread_join(tid, (void **)&ret);
if (ret == PTHREAD_CANCELED)
printf("thread has stopped, and exit code: -1\n");
else
printf("some error occured");
return 0;
}
atomic
std::atomic和std::atomic_flag
thread
std::thread和std::this_thread
mutex
std::mutex、std::lock_guard、std::unique_lock
condition_variable
std::condition_variable和std::condition_variable_any
future
std::promise、std::package_task、std::future、std::shared_future、std::async
std::thread成员函数 | 说明(public访问方式) |
---|---|
thread | 4种构造函数 |
get_id | 线程id |
joinable | 是否可连接 |
join | 连接,阻塞函数 |
native_handle | 操作系统相关的原生线程句柄(需要本地库支持) |
swap | 线程交换 |
detach | 分离线程 |
g++ -o test test.cpp -lpthread -sd=c++11
thread();
//线程不会马上运行
#include
#include
#include // std::chrono::seconds
#include // std::cout
#include // std::thread, std::this_thread::sleep_for
using namespace std;
void thfunc(int n)
{
std::cout << "thfunc:" << n << endl;
}
int main(int argc, const char *argv[])
{
std::thread threads[5];
std::cout << "create 5 threads...\n";
for (int i = 0; i < 5; i++)
threads[i] = std::thread(thfunc, i + 1);
for (auto &t : threads)
t.join();
std::cout << "All threads joined.\n";
return EXIT_SUCCESS;
}
templace <class Fn, class... Args>
explicit thread(Fn&& fn, Args&&... args);
void join();
#include
#include
using namespace std;
void th_function()
{
std::cout << "i am c++11 thread func" << std::endl;
}
int main(int argc, char *argv[])
{
std::thread t(th_function);
t.join();
return 0;
}
#include
#include
using namespace std;
void thfunc(int n)
{
cout << "thfunc: " << n << "\n";
}
int main(int argc, char *argv[])
{
thread t(thfunc, 1);
t.join();
return 0;
}
#include
#include
using namespace std;
void thfunc(char *s)
{
cout << "thfunc: " << s << "\n";
}
int main(int argc, char *argv[])
{
char s[] = "boy and girl";
thread t(thfunc, s);
t.join();
return 0;
}
#include
#include
using namespace std;
typedef struct
{
int n;
const char *str;
} MYSTRUCT;
void thfunc(void *arg)
{
MYSTRUCT *p = (MYSTRUCT *)arg;
cout << "in thfunc: n=" << p->n << ", str=" << p->str << endl;
}
int main(int argc, char *argv[])
{
MYSTRUCT mystruct{110, "hello world"};
thread t(thfunc, &mystruct);
t.join();
return 0;
}
#include
#include
using namespace std;
void thfunc(int n, int m, int *k, char s[])
{
cout << "in thfunc: n=" << n << ", m=" << m << ", k=" << *k << "\nstr=" << s << endl;
*k = 5000;
}
int main(int argc, char *argv[])
{
int n = 110, m = 200, k = 5;
char str[] = "hello world";
thread t(thfunc, n, m, &k, str);
t.join();
cout << "k=" << k << endl;
return 0;
}
void detach();
#include
#include
using namespace std;
void thfunc(int n, int m, int *k, char s[])
{
cout << "in thfunc: n=" << n << ", m=" << m << ", k=" << *k << "\nstr=" << s << endl;
*k = 5000;
}
int main(int argc, char *argv[])
{
int n = 110, m = 200, k = 5;
char str[] = "hello world";
thread t(thfunc, n, m, &k, str);
t.detach();
cout << "k=" << k << endl;
pthread_exit(NULL);
cout << "this line will not run" << endl;
return 0;
}
thread(thread&& x);
#include
#include
using namespace std;
void fun(int &n)
{
cout << "fun: " << n << "\n";
n += 20;
this_thread::sleep_for(chrono::milliseconds(10));
}
int main()
{
int n = 0;
cout << "n=" << n << '\n';
n = 10;
thread t1(fun, ref(n));
thread t2(move(t1));
t2.join();
cout << "n=" << n << '\n';
return 0;
}
thread::id get_id()
#include // std::cout
#include // std::thread, std::thread::id, std::this_thread::get_id
using namespace std;
thread::id main_thread_id = this_thread::get_id();
void is_main_thread()
{
if (main_thread_id == this_thread::get_id())
std::cout << "This is the main thread.\n";
else
std::cout << "This is not the main thread.\n";
}
int main()
{
is_main_thread();
thread th(is_main_thread);
th.join();
return 0;
}
this_thread引用当前线程。
//线程放弃执行,回到就绪态
void yield();//让出线程CPU时间片,让其它线程有机会执行。
#include // std::cout
#include // std::thread, std::this_thread::yield
#include // std::atomic
using namespace std;
atomic<bool> ready(false);
void thfunc(int id)
{
while (!ready)
this_thread::yield();
for (volatile int i = 0; i < 1000000; ++i)
{
}
cout << id << ",";
}
int main()
{
cout << "race of 10 threads that count to 1 million:\n";
thread threads[10];
for (int i = 0; i < 10; ++i)
threads[i] = thread(thfunc, i);
ready = true;
for (auto &th : threads)
th.join();
cout << '\n';
return 0;
}
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
#include // std::cout
#include // std::this_thread::sleep_until
#include // std::chrono::system_clock
#include // std::time_t, std::tm, std::localtime, std::mktime
#include
#include
using namespace std;
void getNowTime()
{
timespec time;
clock_gettime(CLOCK_REALTIME, &time);
struct tm nowTime;
localtime_r(&time.tv_sec, &nowTime);
printf("%04d-%02d-%02d %02d:%02d:%02d\n",
nowTime.tm_year + 1900,
nowTime.tm_mon + 1,
nowTime.tm_mday,
nowTime.tm_hour,
nowTime.tm_min,
nowTime.tm_sec);
}
int main()
{
using std::chrono::system_clock;
std::time_t tt = system_clock::to_time_t(system_clock::now());
struct std::tm *ptm = std::localtime(&tt);
getNowTime();
cout << "Waiting for the next minute to begin...\n";
++ptm->tm_min;
ptm->tm_sec = 0;
this_thread::sleep_until(system_clock::from_time_t(mktime(ptm)));
getNowTime();
return 0;
}
#include // std::cout, std::endl
#include // std::this_thread::sleep_for
#include // std::chrono::seconds
int main()
{
std::cout << "countdown:\n";
for (int i = 5; i > 0; --i)
{
std::cout << i << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "Lift off!\n";
return 0;
}
保证共享资源的稳定性,使用线程同步机制调整多个线程的执行顺序。只有拥有锁的线程才能操作共享资源,其它线程等待。
异步是当调用或请求发送给被调用者时,调用者不用等待结果返回而继续当前处理。实现异步机制的方式有多线程、中断和消息等。
同步机制消除并发和异步机制带来的线程资源竞争无序性的复杂度,实现线程间有序正确地共享数据,以一致的顺序执行一组操作。
#include
#include
#include
#include
#include
#include
int gcn;
void *thread_1(void *arg)
{
for (int j = 0; j < 10000000; j++)
gcn++;
pthread_exit((void *)0);
}
void *thread_2(void *arg)
{
for (int j = 0; j < 10000000; j++)
gcn++;
pthread_exit((void *)0);
}
int main(void)
{
for (int j = 0; j < 10; j++)
{
gcn = 0;
pthread_t th1, th2;
int err = pthread_create(&th1, NULL, thread_1, (void *)0);
if (err != 0)
{
printf("create new thread error:%s\n", strerror(err));
exit(0);
}
err = pthread_create(&th2, NULL, thread_2, (void *)0);
if (err != 0)
{
printf("create new thread error:%s\n", strerror(err));
exit(0);
}
err = pthread_join(th1, NULL);
if (err != 0)
{
printf("wait thread done error:%s\n", strerror(err));
exit(1);
}
err = pthread_join(th2, NULL);
if (err != 0)
{
printf("wait thread done error:%s\n", strerror(err));
exit(1);
}
printf("gcn=%d\n", gcn);
}
return 0;
}
#include
#include
#include
#include
using namespace std;
int a = 200;
int b = 100;
void* ThreadA(void*)
{
while (1)
{
a -= 50;
b += 50;
}
}
void* ThreadB(void*)
{
while (1)
{
cout <<a+b<<endl;
sleep(1);
}
}
int main()
{
pthread_t tida, tidb;
pthread_create(&tida, NULL, ThreadA, NULL);
pthread_create(&tidb, NULL, ThreadB, NULL);
//pthread_join(tida, NULL);
pthread_join(tidb, NULL);
return 1;
}
临界资源,指一次仅允许一个线程使用的共享资源,各线程应该互斥对其访问。每个线程中访问临界资源的那段代码称为临界(区|段)(Critical Section)。
#include
pthread_mutex_t mutex;
//函数初始化,动态方式,需要销毁
//restrict,只用于限定指针,告知编译器,只能通过该指针修改期指向内容。
//帮助编译器进行代码优化,生成更有效率的汇编代码。
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
//宏PTHREAD_MUTEX_INITIALIZER静态初始化,常量初始化,不需要销毁
#define PTHREAD_MUTEX_INITIALIZER \
{{0,0,0,0,0,{0}}}
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
//或者
pthread_mutex_t pmutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(pmutex , NULL);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
#include
#include
#include
#include
#include
#include
int gcn;
pthread_mutex_t mutex;
void *thread_1(void *arg)
{
for (int j = 0; j < 10000000; j++)
{
pthread_mutex_lock(&mutex);
gcn++;
pthread_mutex_unlock(&mutex);
}
pthread_exit((void *)0);
}
void *thread_2(void *arg)
{
for (int j = 0; j < 10000000; j++)
{
pthread_mutex_lock(&mutex);
gcn++;
pthread_mutex_unlock(&mutex);
}
pthread_exit((void *)0);
}
int main(void)
{
pthread_mutex_init(&mutex, NULL);
for (int j = 0; j < 10; j++)
{
gcn = 0;
pthread_t th1, th2;
int err = pthread_create(&th1, NULL, thread_1, (void *)0);
if (err != 0)
{
printf("create new thread error:%s\n", strerror(err));
exit(0);
}
err = pthread_create(&th2, NULL, thread_2, (void *)0);
if (err != 0)
{
printf("create new thread error:%s\n", strerror(err));
exit(0);
}
err = pthread_join(th1, NULL);
if (err != 0)
{
printf("wait thread done error:%s\n", strerror(err));
exit(1);
}
err = pthread_join(th2, NULL);
if (err != 0)
{
printf("wait thread done error:%s\n", strerror(err));
exit(1);
}
printf("gcn=%d\n", gcn);
}
pthread_mutex_destroy(&mutex);
return 0;
}
#include
#include
#include
#include
using namespace std;
int a = 200;
int b = 100;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void *ThreadA(void *)
{
while (1)
{
pthread_mutex_lock(&lock);
a -= 50;
b += 50;
pthread_mutex_unlock(&lock);
}
}
void *ThreadB(void *)
{
while (1)
{
pthread_mutex_lock(&lock);
cout << a + b << endl;
pthread_mutex_unlock(&lock);
sleep(1);
}
}
int main()
{
//pthread_mutex_init(&lock, NULL);
pthread_t tida, tidb;
pthread_create(&tida, NULL, ThreadA, NULL);
pthread_create(&tidb, NULL, ThreadB, NULL);
pthread_join(tida, NULL);
pthread_join(tidb, NULL);
//pthread_mutex_destroy(&lock);
return 1;
}
#include
pthread_rwlock_t rwlock;
//宏PTHREAD_RWLOCK_INITIALIZER静态初始化,常量初始化,不需要销毁
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
//函数初始化,动态方式,需要销毁
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
pthread_rwlock_t rwlock;
pthread_rwlock_init(&rwlock, NULL);
//或者
pthread_rwlock_t *prwlock = (pthread_rwlock_t *)malloc(sizeof(pthread_rwlock_t ));
pthread_rwlock_init(prwlock , NULL);
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
//若上锁,不阻塞,立即返回EBUSY
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
//若上锁,不阻塞,立即返回EBUSY
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
//规定时间等待读写锁,等不到返回ETIMEDOUT
int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, const struct timespec *restrict abs_timeout);
int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, const struct timespec *restrict abs_timeout);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int gcn = 0;
pthread_mutex_t mutex;
pthread_rwlock_t rwlock;
void *thread_1(void *arg)
{
volatile int a;
for (int j = 0; j < 10000000; j++)
{
pthread_mutex_lock(&mutex);
a = gcn;
pthread_mutex_unlock(&mutex);
}
pthread_exit((void *)0);
}
void *thread_2(void *arg)
{
volatile int b;
for (int j = 0; j < 10000000; j++)
{
pthread_mutex_lock(&mutex);
b = gcn;
pthread_mutex_unlock(&mutex);
}
pthread_exit((void *)0);
}
void *thread_3(void *arg)
{
volatile int a;
for (int j = 0; j < 10000000; j++)
{
pthread_rwlock_rdlock(&rwlock);
a = gcn;
pthread_rwlock_unlock(&rwlock);
}
pthread_exit((void *)0);
}
void *thread_4(void *arg)
{
volatile int b;
for (int j = 0; j < 10000000; j++)
{
pthread_rwlock_rdlock(&rwlock);
b = gcn;
pthread_rwlock_unlock(&rwlock);
}
pthread_exit((void *)0);
}
int mutextVer()
{
pthread_mutex_init(&mutex, NULL);
struct timeval start;
gettimeofday(&start, NULL);
pthread_t th1, th2;
int err = pthread_create(&th1, NULL, thread_1, (void *)0);
if (err != 0)
{
printf("create new thread error:%s\n", strerror(err));
exit(0);
}
err = pthread_create(&th2, NULL, thread_2, (void *)0);
if (err != 0)
{
printf("create new thread error:%s\n", strerror(err));
exit(0);
}
err = pthread_join(th1, NULL);
if (err != 0)
{
printf("wait thread done error:%s\n", strerror(err));
exit(1);
}
err = pthread_join(th2, NULL);
if (err != 0)
{
printf("wait thread done error:%s\n", strerror(err));
exit(1);
}
struct timeval end;
gettimeofday(&end, NULL);
pthread_mutex_destroy(&mutex);
long long total_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
total_time /= 1000;
printf("total mutex time is %lld ms\n", total_time);
return 0;
}
int rdlockVer()
{
pthread_rwlock_init(&rwlock, NULL);
struct timeval start;
gettimeofday(&start, NULL);
pthread_t th1, th2;
int err = pthread_create(&th1, NULL, thread_3, (void *)0);
if (err != 0)
{
printf("create new thread error:%s\n", strerror(err));
exit(0);
}
err = pthread_create(&th2, NULL, thread_4, (void *)0);
if (err != 0)
{
printf("create new thread error:%s\n", strerror(err));
exit(0);
}
err = pthread_join(th1, NULL);
if (err != 0)
{
printf("wait thread done error:%s\n", strerror(err));
exit(1);
}
err = pthread_join(th2, NULL);
if (err != 0)
{
printf("wait thread done error:%s\n", strerror(err));
exit(1);
}
struct timeval end;
gettimeofday(&end, NULL);
pthread_rwlock_destroy(&rwlock);
long long total_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
total_time /= 1000;
printf("total mutex time is %lld ms\n", total_time);
return 0;
}
int main()
{
mutextVer();
rdlockVer();
return 0;
}
pthread_mutex_t mutex;
#define N 100
int count = 0;
//生产者线程
void procedure() {
int item;
while(1) {
item = produce_item(); //生成数据项
if(count == N) //缓冲区满了
sleep();
pthread_mutex_lock(&mutex);
insert_item(item); //数据项放入缓冲区
count = count + 1;
pthread_mutex_unlock(&mutex);
if(count == 1) //消费者等待
wakeup(consumer); //唤醒消费者
}
}
//消费者线程
void consumer() {
int item;
while(1) {
if(count == 0) //缓冲区空了
sleep();
pthread_mutex_lock(&mutex);
item = remove_item(); //取走数据项
count = count - 1;
pthread_mutex_unlock(&mutex);
if(count == N - 1) //缓冲区有空槽
wakeup(procedure); //唤醒生成者
}
}
消费者从解锁到休眠这段代码有可能被打断,而条件变量将互斥锁释放到休眠当作原子操作,不容打断。
pthread_cont_t cond = PTHREAD_COND_INITIALLER;
动态初始化,需要销毁
pthread_cont_t cond;
pthread_cond_init(&cond, NULL);
//和
pthread_cont_t *pcond = (pthread_cont_t *)malloc(sizeof(pthread_cont_t));
pthread_cond_init(pcond, NULL);
#include
typedef struct {
pthread_mutex_t mutex;
pthread_cond_t cond;
int value;
} my_struct_t ;
my_struct_t data = {
PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0
};
int main() {
return 0;
}
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
typedef struc timespec {
time_t tv_sec; //秒
long tv_nsex; //纳秒
} timespec_t ;
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
lock(mutex)
while(condition is false)
cond_wait(cond, mutex, timeout)
dosomething()
unlock(mutex)
条件变量必须和互斥锁联合使用。能够保证互斥锁解锁到线程被条件变量阻塞,互斥锁上锁到线程被唤醒都是原子操作。
while循环用于判断是否虚假唤醒(Spurious Wakeups),条件不一定满足。
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_destroy(pthread_cond_t *cond);
#include
#include
#include
#include
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int i = 1;
void *thread1(void *junk) {
while(i <= 20) {
pthread_mutex_lock(&mutex);
if(i%3 == 0)
pthread_cond_signal(&cond);
else
print("thread1: %d\n", i);
pthread_mutex_unlock(&mutex);
sleep(1);
i++;
}
}
void *thread2(void *junk) {
while(i < 20) {
pthread_mutex_lock(&mutex);
if(i%3 != 0)
pthread_cond_wait(&cond, &mutex);
print("thread2: %d\n", i);
pthread_mutex_unlock(&mutex);
sleep(1);
i++;
}
}
int main() {
//pthread_mutex_init(&mutex, NULL);
//pthread_cond_init(&cond, NULL);
pthread_t t_a;
pthread_t t_b;
pthread_cteate(&t_a, NULL, thread2, NULL);
pthread_cteate(&t_b, NULL, thread1, NULL);
pthread_join(t_b, NULL);
//pthread_mutex_destroy(&mutex);
//pthread_cond_destroy(&cond);
return 0;
}
mutex(基本互斥锁)、recursive_mutex(递归互斥锁)、timed_mutex(定时互斥锁)、recursive_timed_mutex(定时递归互斥锁)
lock、try_lock、unlock
std::mutex成员函数 | 说明 |
---|---|
mutex | 构造函数 |
lock | 上锁 |
try_lock | 尝试上锁 |
native_handle | 本地互斥锁句柄 |
void lock();
void unlock();
#include // std::cout
#include // std::thread
#include // std::mutex
volatile int counter(0); // non-atomic counter
std::mutex mtx; // locks access to counter
void thrfunc()
{
for (int i = 0; i < 10000; ++i)
{
mtx.lock();
++counter;
mtx.unlock();
}
}
int main(int argc, const char *argv[])
{
std::thread threads[10];
for (int i = 0; i < 10; ++i)
threads[i] = std::thread(thrfunc);
for (auto &th : threads)
th.join();
std::cout << "count to " << counter << " successfully \n";
return 0;
}
增加定时功能
std::timed_mutex成员函数 | 说明 |
---|---|
timed_mutex | 构造函数 |
lock | 上锁 |
try_lock | 尝试上锁 |
try_lock_for | 一段时间尝试上锁 |
try_lock_until | 时间点前尝试上锁 |
native_handle | 本地互斥锁句柄 |
#include // std::cout
#include // std::thread
#include // std::mutex
volatile int counter(0);
std::timed_mutex mtx;
void thrfunc()
{
for (int i = 0; i < 10000; ++i)
{
if (mtx.try_lock_for(std::chrono::milliseconds(10)))
{
++counter;
mtx.unlock();
}
else
std::cout << "try_lock false\n";
}
}
int main(int argc, const char *argv[])
{
std::thread threads[10];
for (int i = 0; i < 10; ++i)
threads[i] = std::thread(thrfunc);
for (auto &th : threads)
th.join();
std::cout << "count to " << counter << " successfully \n";
return 0;
}
一堆已经创建好了的线程,初始时处于空闲等待状态,当需要处理新任务时,线程池中取出一个空闲等待的线程来处理该任务,任务处理完毕后该线程放回池中(线程状态设置为空闲)。
与进程比较,线程的创建和销毁是轻量级的(开销较小),但大量创建和销毁线程时,开销合在一起就比较大。线程池可以线程复用,避免无谓的开销。
c 线程池
#include
#include
#include
#include
typedef struct
{
void (*function)(void *arg);
void *arg;
} Task;
typedef struct
{
Task *taskQ; // 任务队列
int queueCapacity; // 容量
int queueSize; // 当前任务个数
int queueFront; // 队头 -> 取数据
int queueRear; // 队尾 -> 放数据
pthread_t managerID; // 管理者线程ID
pthread_t *threadIDs; // 工作的线程ID
int minNum; // 最小线程数量
int maxNum; // 最大线程数量
int busyNum; // 忙的线程的个数
int liveNum; // 存活的线程的个数
int exitNum; // 要销毁的线程个数,= liveNum - busyNum
pthread_mutex_t mutexPool; // 锁整个的线程池
pthread_mutex_t mutexBusy; // 锁busyNum变量
pthread_cond_t notFull; // 任务队列是不是满了
pthread_cond_t notEmpty; // 任务队列是不是空了
int shutdown; // 是不是要销毁线程池, 销毁为1, 不销毁为0
} ThreadPool;
// 当前工作线程个数
int threadPoolBusyNum(ThreadPool *pool)
{
pthread_mutex_lock(&pool->mutexBusy);
int busyNum = pool->busyNum;
pthread_mutex_unlock(&pool->mutexBusy);
return busyNum;
}
// 当前活着的线程的个数
int threadPoolAliveNum(ThreadPool *pool)
{
pthread_mutex_lock(&pool->mutexPool);
int aliveNum = pool->liveNum;
pthread_mutex_unlock(&pool->mutexPool);
return aliveNum;
}
// 线程池退出
void threadExit(ThreadPool *pool)
{
pthread_t tid = pthread_self();
pthread_mutex_lock(&pool->mutexPool);
for (int i = 0; i < pool->maxNum; i++)
{
if (pool->threadIDs[i] == tid)
{
pool->threadIDs[i] = 0;
pool->liveNum--;
printf("threadExit() called, %ld exiting...\n", tid);
break;
}
}
pthread_mutex_unlock(&pool->mutexPool);
pthread_exit(NULL);
}
// 工作的线程(消费者线程)任务函数
void *worker(void *arg)
{
ThreadPool *pool = (ThreadPool *)arg;
while (1)
{
pthread_mutex_lock(&pool->mutexPool);
// 当前任务队列是否为空
while (pool->queueSize == 0 && !pool->shutdown)
{
// 阻塞工作线程
pthread_cond_wait(&pool->notEmpty, &pool->mutexPool);
// 判断是否用销毁线程
if (pool->exitNum > 0) // 启动线程冗余
{
pool->exitNum--;
if (pool->liveNum > pool->minNum)
{
pool->liveNum--;
pthread_mutex_unlock(&pool->mutexPool);
threadExit(pool);
}
}
}
// 判断线程池是否被关闭
if (pool->shutdown)
{
pthread_mutex_unlock(&pool->mutexPool);
threadExit(pool);
}
// 从任务队列中取出一个任务
Task task;
task.function = pool->taskQ[pool->queueFront].function;
task.arg = pool->taskQ[pool->queueFront].arg;
// 移动头节点
pool->queueFront = (pool->queueFront + 1) % pool->queueCapacity;
pool->queueSize--;
// 解锁
pthread_mutex_unlock(&pool->mutexPool);
pthread_cond_signal(&pool->notFull); // 通知线程池可以添加任务
printf("thread %ld start working...\n", pthread_self());
pthread_mutex_lock(&pool->mutexBusy);
pool->busyNum++;
pthread_mutex_unlock(&pool->mutexBusy);
// 执行
task.function(task.arg);
free(task.arg);
task.arg = NULL;
printf("thread %ld end working...\n", pthread_self());
pthread_mutex_lock(&pool->mutexBusy);
pool->busyNum--;
pthread_mutex_unlock(&pool->mutexBusy);
}
threadExit(pool);
// return NULL;
}
// 管理者线程任务函数
// 动态增删线程数
void *manager(void *arg)
{
ThreadPool *pool = (ThreadPool *)arg;
while (!pool->shutdown)
{
// 3s检查一次
sleep(3);
// 取出线程池任务的数量和当前线程的数量
pthread_mutex_lock(&pool->mutexPool);
int queueSize = pool->queueSize;
int liveNum = pool->liveNum;
printf("liveNum = %d\n", liveNum);
pthread_mutex_unlock(&pool->mutexPool);
// 取出忙的线程的数量
pthread_mutex_lock(&pool->mutexBusy);
int busyNum = pool->busyNum;
printf("busyNum = %d\n", busyNum);
pthread_mutex_unlock(&pool->mutexBusy);
// 添加线程
// 任务的个数 > 成活的线程个数 && 存活的线程数 < 最大线程数
if (queueSize > liveNum && liveNum < pool->maxNum)
{
pthread_mutex_lock(&pool->mutexPool);
for (int i = 0; i < pool->maxNum && pool->liveNum < pool->maxNum; i++)
{
if (pool->threadIDs[i] == 0)
{
pthread_create(&pool->threadIDs[i], NULL, worker, pool); // 创建新线程
pool->liveNum++;
}
}
pthread_mutex_unlock(&pool->mutexPool);
}
// 销毁线程
// 条件是:忙的线程*2 < 存活的线程数 && 存活的线程 > 最小线程数
// 我觉得,释放多余内存
if (busyNum * 2 < liveNum && liveNum > pool->minNum)
{
pthread_mutex_lock(&pool->mutexPool);
int NUMBER = pool->liveNum - pool->busyNum;
pool->exitNum = NUMBER;
pthread_mutex_unlock(&pool->mutexPool);
// 发信号让线程自杀,具体实现就是每个线程的有一个销毁判断
// 每次销毁一个,pool->exitNum--,直到为0
for (int i = 0; i < NUMBER; i++)
pthread_cond_signal(&pool->notEmpty);
}
}
pthread_cond_broadcast(&pool->notEmpty);
return NULL;
}
// 创建线程池并初始化
ThreadPool *threadPoolCreate(int min, int max, int queueSize)
{
ThreadPool *pool = (ThreadPool *)malloc(sizeof(ThreadPool));
do
{
if (pool == NULL)
{
printf("malloc ThreadPool failed\n");
break;
}
pool->threadIDs = (pthread_t *)malloc(sizeof(pthread_t) * max);
if (pool->threadIDs == NULL)
{
printf("malloc threadIDs failed\n");
break;
}
// memset(pool->threadIDs, 0, sizeof(pthread_t) * max);
for (int i = 0; i < max; i++)
pool->threadIDs[i] = 0;
pool->minNum = min;
pool->maxNum = max;
pool->busyNum = 0;
pool->liveNum = min;
pool->exitNum = 0;
if (pthread_mutex_init(&pool->mutexPool, NULL) != 0 ||
pthread_mutex_init(&pool->mutexBusy, NULL) != 0 ||
pthread_cond_init(&pool->notEmpty, NULL) != 0 ||
pthread_cond_init(&pool->notFull, NULL) != 0)
{
printf("mutex or cond init failed\n");
break;
}
// 任务队列
pool->taskQ = (Task *)malloc(sizeof(Task) * queueSize);
if (pool->taskQ == NULL)
{
printf("malloc taskQ failed\n");
break;
}
pool->queueCapacity = queueSize;
pool->queueSize = 0;
pool->queueFront = 0;
pool->queueRear = 0;
pool->shutdown = 0;
if (pthread_create(&pool->managerID, NULL, manager, pool))
{
perror("create pthread_create managerID failed");
break;
}
for (int i = 0; i < min; i++)
{
if (pthread_create(&pool->threadIDs[i], NULL, worker, pool))
{
perror("create pthread_create threadIDs failed");
break;
}
}
return pool;
} while (0);
// 初始化失败,释放资源
if (pool && pool->threadIDs)
free(pool->threadIDs);
if (pool && pool->taskQ)
free(pool->taskQ);
if (pool)
free(pool);
return NULL;
}
// 线程池添加任务
void threadPoolAdd(ThreadPool *pool, void (*func)(void *), void *arg)
{
pthread_mutex_lock(&pool->mutexPool);
// 因为任务队列满了或者线程池需要销毁,阻塞生产者线程
while (pool->queueSize == pool->queueCapacity && !pool->shutdown)
pthread_cond_wait(&pool->notFull, &pool->mutexPool);
if (pool->shutdown)
{
pthread_mutex_unlock(&pool->mutexPool);
return;
}
// 添加任务
pool->taskQ[pool->queueRear].function = func;
pool->taskQ[pool->queueRear].arg = arg;
pool->queueRear = (pool->queueRear + 1) % pool->queueCapacity;
pool->queueSize++;
pthread_mutex_unlock(&pool->mutexPool);
pthread_cond_signal(&pool->notEmpty);
}
// 销毁线程池, 失败-1,成功0
int threadPoolDestroy(ThreadPool *pool)
{
if (pool == NULL)
return -1;
// 关闭线程池
pool->shutdown = -1;
// 等待管理者线程结束
pthread_join(pool->managerID, NULL);
printf("manager thread quit!\n");
// 唤醒阻塞的消费者线程(工作线程)
for (int i = 0; i < pool->liveNum; i++)
pthread_cond_signal(&pool->notEmpty);
// 等待工作线程结束
//pthread_mutex_lock(&pool->mutexPool);
for (int i = 0; i < pool->maxNum; i++)
{
if (pool->threadIDs[i] != 0)
{
pthread_join(pool->threadIDs[i], NULL);
pool->threadIDs[i] = 0;
pool->liveNum--;
}
}
//pthread_mutex_unlock(&pool->mutexPool);
printf("work threads quit!\n");
// 释放堆内存
if (pool->taskQ)
free(pool->taskQ);
if (pool->threadIDs)
free(pool->threadIDs);
// 销毁互斥量,条件变量
pthread_mutex_destroy(&pool->mutexPool);
pthread_mutex_destroy(&pool->mutexBusy);
pthread_cond_destroy(&pool->notEmpty);
pthread_cond_destroy(&pool->notFull);
free(pool);
pool = NULL;
return 0;
}
// 测试案例
void taskFunc(void *arg)
{
int num = *(int *)arg;
printf("taskFunc thread %ld is working, number = %d\n", pthread_self(), num);
// sleep(3);
}
int main()
{
#define N 130
ThreadPool *pool = threadPoolCreate(5, 15, 100);
for (int i = 0; i < N; i++)
{
int *num = (int *)malloc(sizeof(int));
*num = i + 100;
threadPoolAdd(pool, taskFunc, num);
}
sleep(1);
threadPoolDestroy(pool);
printf("Over!\n");
return 0;
}
C++线程池
#include
#include
#include
#include
#include
using namespace std;
class CTask
{
public:
CTask(void *ptrData = nullptr) : m_ptrData(ptrData) {}
virtual ~CTask() {}
virtual void Run() = 0;
protected:
void *m_ptrData;
};
class CMyTask : public CTask
{
public:
CMyTask(void *ptrData = nullptr) : CTask(ptrData) {}
void Run()
{
printf("%s\n", (char *)m_ptrData);
sleep(rand() % 4 + 1);
}
};
class CThreadPool
{
private:
static vector<CTask *> m_vecTaskList;
static bool shutdown;
static pthread_mutex_t m_pthreadMutex;
static pthread_cond_t m_pthreadCond;
int m_iThreadNum;
pthread_t *pthread_id;
protected:
static void *ThreadFunc(void *threadData);
// static int MoveToIdle(pthread_t tid);
// static int MoveToBusy(pthread_t tid);
void Create()
{
pthread_id = new pthread_t[m_iThreadNum];
for (int i = 0; i < m_iThreadNum; i++)
pthread_create(&pthread_id[i], NULL, ThreadFunc, NULL);
}
public:
static int getTaskSize();
CThreadPool(int threadNum) : m_iThreadNum(threadNum)
{
printf("I will create %d threads.\n", threadNum);
Create();
}
void AddTask(CTask *task)
{
pthread_mutex_lock(&m_pthreadMutex);
m_vecTaskList.push_back(task);
pthread_mutex_unlock(&m_pthreadMutex);
pthread_cond_signal(&m_pthreadCond);
}
int StopAll()
{
if (shutdown)
return -1;
printf("Now I will end all threads!\n\n");
pthread_mutex_lock(&m_pthreadMutex);
shutdown = true;
pthread_mutex_unlock(&m_pthreadMutex);
pthread_cond_broadcast(&m_pthreadCond);
for (int i = 0; i < m_iThreadNum; i++)
pthread_join(pthread_id[i], NULL);
delete[] pthread_id;
pthread_id = NULL;
// pthread_mutex_destroy(&m_pthreadMutex);
// pthread_mutex_destroy(&m_pthreadCond);
return 0;
}
};
vector<CTask *> CThreadPool::m_vecTaskList;
bool CThreadPool::shutdown = false;
pthread_mutex_t CThreadPool::m_pthreadMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t CThreadPool::m_pthreadCond = PTHREAD_COND_INITIALIZER;
int CThreadPool::getTaskSize()
{
return m_vecTaskList.size();
}
void *CThreadPool::ThreadFunc(void *threadData)
{
pthread_t tid = pthread_self();
while (true)
{
pthread_mutex_lock(&m_pthreadMutex);
while (getTaskSize() == 0 && !shutdown)
pthread_cond_wait(&m_pthreadCond, &m_pthreadMutex);
if (shutdown)
{
pthread_mutex_unlock(&m_pthreadMutex);
printf("[tid: %lu]\texit\n", tid);
pthread_exit(NULL);
}
printf("[tid: %lu]\trun: ", tid);
vector<CTask *>::iterator iter = m_vecTaskList.begin();
CTask *task = *iter;
m_vecTaskList.erase(iter);
pthread_mutex_unlock(&m_pthreadMutex);
task->Run();
printf("[tid: %lu]\tidle\n", tid);
}
return (void *)0;
}
int main()
{
if (true)
{
CThreadPool threadpool(5);
string str[10];
for (int i = 0; i < 10; i++)
{
str[i] = string("hello ") + to_string(i);
threadpool.AddTask(new CMyTask((void *)(str[i].c_str())));
}
while (true)
{
printf("There are still %d tasks need to handle\n", CThreadPool::getTaskSize());
if (CThreadPool::getTaskSize() == 0)
{
if (threadpool.StopAll() == -1)
{
printf("Thread pool clear, exit.\n");
break;
}
}
sleep(2);
printf("2 seconds later...\n");
}
}
return 0;
}
#include
#include
#include
#include
#include
#include
using namespace std;
#define testout(msg) cout << msg << endl
class XTask
{
public:
virtual ~XTask() {}
// 一客户端一个base
// struct event_base *base = 0;
// 线程池id
// int thread_id = 0;
// 初始化任务
virtual void Init(int arg) = 0;
};
class CMyTask : public XTask
{
public:
void Init(int arg)
{
for (long long c = 0; c < 10000000; c++)
for (long long i = 0; i < 10000000; i++)
;
printf("%d---------%d--------\n", arg, arg);
}
};
class XThread
{
public:
void Main()
{
cout << id << " thread::Main() begin" << endl;
cout << id << " thread::Main() end" << endl;
}
void Start()
{
testout(id << " thread At Start()");
thread th(&XThread::Main, this);
th.detach();
}
void Activate(int arg)
{
testout(id << " thread At Activate()");
mtx.lock();
if (tasks.empty())
{
mtx.unlock();
return;
}
XTask *t = tasks.front();
tasks.pop_front();
mtx.unlock();
t->Init(arg);
}
void AddTask(XTask *t)
{
if (t)
{
// t->base = base;
mtx.lock();
tasks.push_back(t);
mtx.unlock();
}
}
// void Notify();
int id = 0;
private:
// event_base *base = 0;
list<XTask *> tasks;
mutex mtx;
};
class XThreadPool
{
public:
void Init(int _threadCount)
{
testout("main thread At XThreadPoll::Init()");
threadCount = _threadCount;
lastThread = -1;
for (int i = 0; i < threadCount; i++)
{
cout << "Create thread" << i << endl;
XThread *t = new XThread();
t->id = i;
t->Start();
threads.push_back(t);
this_thread::sleep_for(chrono::milliseconds(10));
}
}
void Dispatch(XTask *task, int arg)
{
testout("main thread At XThreadPoll::dispathch()");
if (task)
{
int tid = (lastThread + 1) % threadCount;
lastThread = tid;
XThread *t = threads[tid];
t->AddTask(task);
t->Activate(arg);
}
}
private:
int threadCount;
int lastThread = -1;
vector<XThread *> threads;
};
int main()
{
{
#define N 10
XThreadPool threadpool;
threadpool.Init(N); // 初始化线程池
CMyTask task[N];
for (int i = 0; i < N; i++)
threadpool.Dispatch(&task[i], i); // 分配任务
#undef N
}
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
class XTask
{
public:
virtual ~XTask() {}
void setData(void *_data)
{
data = _data;
}
virtual void Run() = 0;
protected:
void *data = NULL;
};
class CMyTask : public XTask
{
public:
void Run()
{
int n = *(int *)data;
cout << "Task " << n << " start" << endl;
for (int c = 0; c < 1000; c++)
for (int i = 0; i < 1000; i++)
;
cout << "Task " << n << " end" << endl;
}
};
class XThread
{
public:
void Main()
{
thread::id id = this_thread::get_id();
cout << "Thread " << id << " start" << endl;
while (true)
{
XTask *t;
{
unique_lock<mutex> lk(mtx);
while (tasks.empty() && !quit)
cv.wait(lk);
if (quit)
{
cout << "Thread " << id << " quit" << endl;
break;
}
t = tasks.front();
tasks.pop_front();
}
t->Run();
}
cout << "Thread " << id << " end" << endl;
}
void AddTask(XTask *t)
{
mtx.lock();
cout << "AddTask" << endl;
tasks.push_back(t);
cout << "TaskSize: " << tasks.size() << endl;
mtx.unlock();
cv.notify_one();
}
XThread()
{
quit = false;
t = thread(&XThread::Main, this);
}
~XThread()
{
mtx.lock();
quit = true;
mtx.unlock();
cv.notify_one();
t.join();
}
private:
bool quit;
thread t;
deque<XTask *> tasks;
mutex mtx;
condition_variable cv;
};
class XThreadPool
{
public:
XThreadPool(int _threadCount = 10) : threadCount(_threadCount)
{
for (int i = 0; i < threadCount; i++)
{
threads.push_back(new XThread());
// this_thread::sleep_for(chrono::milliseconds(10));
}
lastThread = -1;
}
~XThreadPool()
{
for (int i = 0; i < threadCount; i++)
delete threads[i];
}
void Dispatch(XTask *task)
{
lastThread = (lastThread + 1) % threadCount;
threads[lastThread]->AddTask(task);
}
private:
int threadCount;
int lastThread;
vector<XThread *> threads;
};
int main()
{
if (false)
{
#define N 100
CMyTask task[N];
int data[N];
XThread t;
for (int i = 0; i < N; i++)
{
data[i] = i;
task[i].setData((void *)&data[i]);
t.AddTask(&task[i]);
}
sleep(1);
#undef N
}
if (true)
{
#define N 100
CMyTask task[N];
int data[N];
XThreadPool threadpool;
for (int i = 0; i < N; i++)
{
data[i] = i;
task[i].setData((void *)&data[i]);
threadpool.Dispatch(&task[i]);
}
sleep(1);
#undef N
}
return 0;
}