pthread_create函数
创建一个新线程,并行的执行任务。
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
返回值:成功:0; 失败:错误号。
参数:
pthread_t:当前Linux中可理解为:typedef unsigned long int pthread_t;
参数1:传出参数,保存系统为我们分配好的线程ID
参数2:通常传NULL,表示使用线程默认属性。若想使用具体属性也可以修改该参数。
参数3:函数指针,指向线程主函数(线程体),该函数运行结束,则线程结束。
参数4:线程主函数执行期间所使用的参数。
在一个线程中调用pthread_create()创建新的线程后,当前线程从pthread_create()
返回继续往下执行,而新的线程所执行的代码由我们传给pthread_create的函数指针start_routine决定。
start_routine函数接收一个参数,
是通过pthread_create的arg参数传递给它的,该参数的类型为void *,
这个指针按什么类型解释由调用者自己定义。
start_routine的返回值类型也是void *,
这个指针的含义同样由调用者自己定义。
start_routine返回时,这个线程就退出了,
其它线程可以调用pthread_join得到start_routine的返回值,
pthread_create成功返回后,新创建的线程的id被填写到
thread参数所指向的内存单元。
attr参数表示线程属性,
互斥锁
typedef struct ct_sum
{
int sum;
pthread_mutex_t lock;
}ct_sum;
pthread_mutex_lock(&(((ct_sum*)cnt)->lock));
---------共享数据文件及操作---------
pthread_mutex_unlock(&(((ct_sum*)cnt)->lock));
pthread_exit(NULL);
#include <pthread.h>//线程头文件
#include <stdio.h>
#include <stdlib.h>
int my_global;//全局变量
void* my_thread_handle(void *arg) //线程执行的函数
{
int val;
val = *((int*)arg);
printf("new thread begin, arg=%d\n", val);
my_global += val;
sleep(3);
pthread_exit(&my_global);//线程结束
// 不再执行
printf("new thread end\n");
}
//gcc m.c -o auto.exe -D_REENTRANT -lpthread //加这个宏保证数据的安全相当于互斥锁(不常用)
int main(void)//创建线程gcc m.c -pthread -o auto.exe 编译需指定pthread这个库
{
pthread_t mythread;//线程句柄
int arg;
int ret;
void *thread_return;//保存指定的线程返回的参数
arg = 100;
my_global = 1000;
printf("my_global=%d\n", my_global);
printf("ready create thread...\n");
ret = pthread_create(&mythread, 0, my_thread_handle, &arg);//创建线程
if (ret != 0) {
printf("create thread failed!\n");
exit(1);
}
printf("wait thread finished...\n");
ret = pthread_join(mythread, &thread_return);//等待指定的线程结束
if (ret != 0) {
printf("pthread_join failed!\n");
exit(1);
}
printf("wait thread end, return value is %d\n", *((int*)thread_return));
printf("my_global=%d\n", my_global);
printf("create thread finished!\n");
}
如果要求最多只允许一个线程进入临界区,则使用互斥量
如果要求多个线程之间的执行顺序满足某个约束,则使用信号量
信号量
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define BUFF_SIZE 80
char buff[BUFF_SIZE];
sem_t sem;//信号量一定要定义为全局
static void* str_thread_handle(void *arg) //线程函数
{
while(1) {
//P(sem)p操作是指判读信号量是否可以开始执行,如果可以执行就执行并将信号量更改
if (sem_wait(&sem) != 0) //信号量p操作第一执行的时候会阻塞在这里,v操作之后信号量为1开始执行
{
printf("sem_wait failed!\n");
exit(1);
}
printf("string is: %slen=%d\n", buff, strlen(buff));
if (strncmp(buff, "end", 3) == 0) {
break;
}
}
}
int main(void)
{
int ret;
pthread_t str_thread;//线程句柄
void *thread_return;//保存指定的线程返回的参数
ret = sem_init(&sem, 0, 0);//初始化信号量
if (ret != 0)
{
printf("sem_init failed!\n");
exit(1);
}
ret = pthread_create(&str_thread, 0, str_thread_handle, 0);//创建线程
if (ret != 0) {
printf("pthread_create failed!\n");
exit(1);
}
while (1) {
fgets(buff, sizeof(buff), stdin);//等待用户输入字符串
//V(sem)//信号量v操作 主线程先执行这个函数 执行了v操作p操作激活子线程开始执行
if (sem_post(&sem) != 0)
{
printf("sem_post failed!\n");
exit(1);
}
if (strncmp(buff, "end", 3) == 0) {
break;
}
}
ret = pthread_join(str_thread, &thread_return);//等待指定线程结束
if (ret != 0) {
printf("pthread_join failed!\n");
exit(1);
}
ret = sem_destroy(&sem);//删除信号量
if (ret != 0) {
printf("sem_destroy failed!\n");
exit(1);
}
return 0;
}
互斥量
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define BUFF_SIZE 80
int global_value = 1000;
pthread_mutex_t lock;//互斥锁
static void* str_thread_handle(void *arg)
{
int i = 0;
for (i=0; i<10; i++) {
pthread_mutex_lock(&lock);//上锁
if (global_value > 0) {
// work
sleep(1);
printf("soled ticket(%d) to ChildStation(%d)\n",
global_value, i+1);
}
global_value--;
pthread_mutex_unlock(&lock);//解锁
sleep(1);
}
}
int main(void)
{
int ret;
pthread_t str_thread;//线程句柄
void *thread_return;//线程返回值
int i;
ret = pthread_mutex_init(&lock, 0);//初始化互斥锁
if (ret != 0) {
printf("pthread_mutex_init failed!\n");
exit(1);
}
ret = pthread_create(&str_thread, 0, str_thread_handle, 0);//创建线程
if (ret != 0) {
printf("pthread_create failed!\n");
exit(1);
}
for (i=0; i<10; i++) {
pthread_mutex_lock(&lock);//上互斥锁
if (global_value > 0) {
// work
sleep(1);
printf("soled ticket(%d) to MainStation(%d)\n",
global_value, i+1);
}
global_value--;
pthread_mutex_unlock(&lock);//解互斥锁
sleep(1);
}
ret = pthread_join(str_thread, &thread_return);//等待指定线程结束
if (ret != 0) {
printf("pthread_join failed!\n");
exit(1);
}
ret = pthread_mutex_destroy(&lock);//释放互斥锁
if (ret != 0) {
printf("pthread_mutex_destroy failed!\n");
exit(1);
}
return 0;
}
条件变量 多线程必备 (用于线程等待信号,当信号发生时线程开始执行 配合互斥锁使用)
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t mutex;//互斥锁
pthread_cond_t cond;//条件变量
void *thread1(void *arg)//线程一执行的函数
{
while (1) {
printf("thread1 is running\n");
pthread_mutex_lock(&mutex);//上互斥锁
//等待条件变量的信号。这个里面会进行解锁,被唤醒时会进行加锁
pthread_cond_wait(&cond, &mutex);
printf("thread1 applied the condition\n");
pthread_mutex_unlock(&mutex);//解互斥锁
sleep(4);
}
}
void *thread2(void *arg)//线程二执行的函数
{
while (1) {
printf("thread2 is running\n");
pthread_mutex_lock(&mutex);//上互斥锁
//等待条件变量的信号。这个里面会进行解锁,被唤醒时会进行加锁
pthread_cond_wait(&cond, &mutex);//等待条件变量的信号
printf("thread2 applied the condition\n");
pthread_mutex_unlock(&mutex);//解互斥锁
sleep(2);
}
}
int main()
{
pthread_t thid1, thid2;
printf("condition variable study!\n");
pthread_mutex_init(&mutex, NULL);//初始化互斥锁
pthread_cond_init(&cond, NULL);//初始化条件变量
pthread_create(&thid1, NULL, (void *)thread1, NULL);//创建线程1
pthread_create(&thid2, NULL, (void *)thread2, NULL);//创建线程2
do {
pthread_cond_signal(&cond);//唤醒某一个等待该条件变量的线程 随机
sleep(1);
} while (1);
return 0;
}
/**************************************************************************************
1.条件变量初始化
pthread_cond_init
原型:int pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr);
参数:cond, 条件变量指针
attr 条件变量高级属性
man 安装: apt-get install manpages-posix-dev
2.唤醒一个等待线程
pthread_cond_signal 通知条件变量,唤醒一个等待者
原型: int pthread_cond_signal (pthread_cond_t *cond);
参数:cond, 条件变量指针
3.唤醒所有等待该条件变量的线程
pthread_cond_broadcast 广播条件变量
原型: int pthread_cond_broadcast (pthread_cond_t *cond);
参数:cond, 条件变量指针
4.等待条件变量/超时被唤醒
pthread_cond_timedwait 等待条件变量cond被唤醒,直到由一个信号或广播,或绝对时间abstime到 *
才唤醒该线程
原型: int pthread_cond_timedwait(
pthread_cond_t *cond,
pthread_mutex_t *mutex,
const struct timespec *abstime);
参数:cond, 条件变量指针
pthread_mutex_t *mutex 互斥量
const struct timespec *abstime 等待被唤醒的绝对超时时间
5.等待条件变量被唤醒
pthread_cond_wait 等待条件变量cond被唤醒(由一个信号或者广播)
原型: int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex);
参数:cond, 条件变量指针
pthread_mutex_t *mutex 互斥量
常见错误码: [EINVAL] cond或mutex无效,
[EINVAL] 同时等待不同的互斥量
[EINVAL] 主调线程没有占有互斥量
6. 释放/销毁条件变量
pthread_cond_destroy 待销毁的条件变量
原型: int pthread_cond_destroy (pthread_cond_t *cond);
参数:cond, 条件变量指针
****************************************************************************************/