int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (void *),
void *arg);
threadpthread_self()获取。attrNULL表示使用默认属性。start_routimevoid *为参数,并返回void *argstart_routime)的数据指针。设置为NULL标识无需传递数据。源码
#include
#include
#include
#include
void *start_routine(void *ptr)
{
printf("子线程(%lu)等待3秒后退出...\n", pthread_self());
sleep(3);
printf("子线程(%lu)即将退出...\n", pthread_self());
return (void *)NULL;
}
int main(int argc, char const *argv[])
{
printf("主线程(%lu)开始运行...\n", pthread_self());
pthread_t thread_id;
{
// 以默认线程属性,创建无数据传递的线程
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&thread_id, &attr, start_routine, NULL);
pthread_attr_destroy(&attr);
// 下面这条语句与上面的四条语句等价
// pthread_create(&thread_id, NULL, start_routine, NULL);
}
printf("主线程(%lu)等待5秒后结束...\n", pthread_self());
sleep(5);
printf("主线程(%lu)即将退出...\n", pthread_self());
exit(EXIT_SUCCESS);
}
输出
主线程(139943698245440)开始运行…
主线程(139943698245440)等待5秒后结束…
子线程(139943698241280)等待3秒后退出…
子线程(139943698241280)即将退出…
主线程(139943698245440)即将退出…
源码
#include
#include
#include
#include
#include
typedef struct _student
{
int id;
int age;
char name[32];
} student;
void *start_routine(void *ptr)
{
printf("子线程(%lu)等待3秒后退出...\n", pthread_self());
sleep(3);
student *pstu = (student *)ptr;
printf("子线程(%lu)接收的数据: name = %s, age = %d, id = %d\n",
pthread_self(), pstu->name, pstu->age, pstu->id);
printf("子线程(%lu)即将退出...\n", pthread_self());
return (void *)NULL;
}
int main(int argc, char const *argv[])
{
printf("主线程(%lu)开始运行...\n", pthread_self());
student stu;
bzero(&stu, sizeof(stu));
strcpy(stu.name, "zhang san");
stu.age = 18;
stu.id = 2022;
pthread_t thread_id;
{
printf("父线程(%lu)传递的数据: name = %s, age = %d, id = %d\n",
pthread_self(), stu.name, stu.age, stu.id);
pthread_create(&thread_id, NULL, start_routine, &stu);
}
printf("主线程(%lu)等待5秒后结束...\n", pthread_self());
sleep(5);
printf("主线程(%lu)即将退出...\n", pthread_self());
exit(EXIT_SUCCESS);
}
输出
主线程(139644495886144)开始运行…
父线程(139644495886144)传递的数据: name = zhang san, age = 18, id = 2022
主线程(139644495886144)等待5秒后结束…
子线程(139644495881984)等待3秒后退出…
子线程(139644495881984)接收的数据: name = zhang san, age = 18, id = 2022
子线程(139644495881984)即将退出…
主线程(139644495886144)即将退出…
#include
#include
int pthread_getcpuclockid(pthread_t thread, clockid_t *clock_id);
int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param);
int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param);
int pthread_setschedprio(pthread_t thread, int prio);
源码
#include
#include
#include
#include
#include
#include
void *start_routine(void *ptr)
{
printf("子线程(%lu)等待3秒后退出...\n", pthread_self());
clockid_t clock_id;
pthread_getcpuclockid(pthread_self(), &clock_id);
printf("子线程(%lu)的CPU时钟ID(%d)\n", pthread_self(), clock_id);
int sched_policy;
struct sched_param param;
pthread_getschedparam(pthread_self(), &sched_policy, ¶m);
printf("子线程(%lu)的调度策略(%s)\n", pthread_self(),
sched_policy == SCHED_FIFO ? "SCHED_FIFO" :
sched_policy == SCHED_RR ? "SCHED_RR" :
sched_policy == SCHED_OTHER ? "SCHED_OTHER" : "???");
printf("子线程(%lu)的调度优先级(%d)\n", pthread_self(), param.sched_priority);
printf("子线程(%lu)即将退出...\n", pthread_self());
return (void *)NULL;
}
int main(int argc, char const *argv[])
{
printf("主线程(%lu)开始运行...\n", pthread_self());
pthread_t thread_id;
pthread_create(&thread_id, NULL, start_routine, NULL);
clockid_t clock_id;
pthread_getcpuclockid(pthread_self(), &clock_id);
printf("主线程(%lu)的CPU时钟ID(%d)\n", pthread_self(), clock_id);
int sched_policy;
struct sched_param param;
pthread_getschedparam(pthread_self(), &sched_policy, ¶m);
printf("主线程(%lu)的调度策略(%s)\n", pthread_self(),
sched_policy == SCHED_FIFO ? "SCHED_FIFO" :
sched_policy == SCHED_RR ? "SCHED_RR" :
sched_policy == SCHED_OTHER ? "SCHED_OTHER" : "???");
printf("主线程(%lu)的调度优先级(%d)\n", pthread_self(), param.sched_priority);
printf("主线程(%lu)等待5秒后结束...\n", pthread_self());
sleep(5);
printf("主线程(%lu)即将退出...\n", pthread_self());
exit(EXIT_SUCCESS);
}
输出
主线程(139759329433408)开始运行…
主线程(139759329433408)的CPU时钟ID(-50154)
子线程(139759329429248)等待3秒后退出…
子线程(139759329429248)的CPU时钟ID(-50162)
子线程(139759329429248)的调度策略(SCHED_OTHER)
子线程(139759329429248)的调度优先级(0)
子线程(139759329429248)即将退出…
主线程(139759329433408)的调度策略(SCHED_OTHER)
主线程(139759329433408)的调度优先级(0)
主线程(139759329433408)等待5秒后结束…
主线程(139759329433408)即将退出…
程序经常需要在不同的线程中使用全局或静态变量,这些变量不同的线程中拥有不同的值。由于同一个进程中的所有线程共享相同的内存空间,因此常规的变量无法实现该需求。
为满足以上需求,提出了线程私有数据的概念。每个线程有一个私有的内存块,这个内存块就是线程的特有区域。该区域使用键值进行索引,使用void *类型。
当创建一个线程时,所有的线程私有数据的键值均为NULL。
typedef unsigned int pthread_key_t;
int pthread_key_create(pthread_key_t *key, void (*destr_function) (void *));
int pthread_key_delete(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, const void *pointer);
void * pthread_getspecific(pthread_key_t key);
pthread_key_create
用于创建一个新的键值。
参数destr_function如果非NULL,指定与键值相关的析构函数。当线程通过pthread_exit或取消操作进行终结时,指定的析构函数被调用,其参数为键值对应的数据。如果赋值为NULL,则不进行调用。如果有多个键值对应的数据需要析构,则其调用的顺序是不确定的。
源码
#include
#include
#include
#include
#include
pthread_key_t key;
void *start_routine(void *ptr)
{
printf("子线程(%lu)开始运行...\n", pthread_self());
pthread_key_t key = *((pthread_key_t *)ptr);
// 主线程向KEY中写入值
int specific_data = 88;
pthread_setspecific(key, &specific_data);
sleep(3);
// 主线程从KEY中获取值
int *p_specific_data = pthread_getspecific(key);
printf("主线程(%lu)的私有数据(%d), 地址(%p)\n", pthread_self(), *p_specific_data, p_specific_data);
printf("子线程(%lu)即将退出...\n", pthread_self());
return (void *)NULL;
}
int main(int argc, char const *argv[])
{
printf("主线程(%lu)开始运行...\n", pthread_self());
// 初始化KEY
pthread_key_create(&key, NULL);
// 主线程向KEY中写入值
int specific_data = 99;
pthread_setspecific(key, &specific_data);
pthread_t thread_id;
pthread_create(&thread_id, NULL, start_routine, &key);
// 主线程从KEY中获取值
int *p_specific_data = pthread_getspecific(key);
printf("主线程(%lu)的私有数据(%d), 地址(%p)\n", pthread_self(), *p_specific_data, p_specific_data);
sleep(5);
// 销毁KEY
pthread_key_delete(key);
printf("主线程(%lu)即将退出...\n", pthread_self());
exit(EXIT_SUCCESS);
}
输出
主线程(140110147004224)开始运行…
主线程(140110147004224)的私有数据(99), 地址(0x7ffe404081f4)
子线程(140110147000064)开始运行…
主线程(140110147000064)的私有数据(88), 地址(0x7f6def8a8ec8)
子线程(140110147000064)即将退出…
主线程(140110147004224)即将退出…
int pthread_equal(pthread_t t1, pthread_t t2);
pthread_once_t once_control = PTHREAD_ONCE_INIT;
int pthread_once(pthread_once_t *once_control, void (*init_routine) (void));
init_routine中的代码最多执行一次源码
#include
#include
#include
#include
#include
pthread_once_t once = PTHREAD_ONCE_INIT;
void init_routine(void)
{
printf("线程(%lu)执行初始化\n", pthread_self());
}
void *start_routine(void *ptr)
{
printf("子线程(%lu)开始运行...\n", pthread_self());
pthread_once(&once, init_routine);
printf("子线程(%lu)即将退出...\n", pthread_self());
return (void*)"9999";
}
int main(int argc, char const *argv[])
{
printf("主线程(%lu)开始运行...\n", pthread_self());
pthread_t thread_id_01;
pthread_create(&thread_id_01, NULL, start_routine, NULL);
pthread_t thread_id_02;
pthread_create(&thread_id_02, NULL, start_routine, NULL);
printf("主线程(%lu)即将退出...\n", pthread_self());
exit(EXIT_SUCCESS);
}
输出
主线程(140486961612608)开始运行…
子线程(140486961608448)开始运行…
线程(140486961608448)执行初始化
子线程(140486961608448)即将退出…
主线程(140486961612608)即将退出…