一段时间没玩linux了,突然发现手生了,但是感觉还在,就是卡卡的,虚拟机装linux的孩子伤不起!!
这个例子是用来捡起线程编程知识:
俩个线程按顺序打印1、2、3、4、5、--9.最终必然是第一个线程打印9.但是此次必须保证线程2在线程1后退出!
以下是代码:
#include "stdio.h"
#include "string.h"
#include "errno.h"
#include <pthread.h>
pthread_t tid1,tid2;
struct msg
{
int flag;
int count ;
pthread_mutex_t lock;
pthread_cond_t cond;
};
void init(struct msg *my_msg )
{
my_msg->flag = 1;
my_msg-> count = 1;
pthread_mutex_init(&(my_msg->lock),NULL);
pthread_cond_init(&(my_msg->cond),NULL);
}
void* thread1_fcn(void *my_msg )
{
while(1)
{
printf("thread1 start!\n");
pthread_mutex_lock(&((struct msg*)my_msg)->lock);
printf("thread1 pthread_cond_wait!\n");
while((((struct msg*)my_msg)->flag)!=1)
{
pthread_cond_wait(&((struct msg*)my_msg)->cond,&((struct msg*)my_msg)->lock);
}
printf("thread1:%d\n",((struct msg*)my_msg)->count);
((struct msg *)my_msg)->count ++;
(((struct msg*)my_msg)->flag) = 2;
pthread_mutex_unlock(&((struct msg*)my_msg)->lock);
pthread_cond_signal(&((struct msg *)my_msg)->cond);
printf("thread1 signal!\n");
if(((struct msg *)my_msg)->count >= 9)
{
//pthread_cond_signal(&((struct msg *)my_msg)->cond);
// pthread_mutex_destroy(&((struct msg*)my_msg)->lock); //is not dynamic malloc
// pthread_cond_destroy(&((struct msg*)my_msg)->cond);
printf("thread1 exit!\n");
break;
// pthread_exit(NULL);
}
}
return NULL;
}
// add thread 1 exit then thread2 exit
void* thread2_fcn(void *my_msg )
{
while(1)
{
printf("thread2 start!\n");
pthread_mutex_lock(&((struct msg*)my_msg)->lock);
printf("thread2 pthread_cond_wait!\n");
while((((struct msg*)my_msg)->flag)!=2)
{
pthread_cond_wait(&((struct msg*)my_msg)->cond,&((struct msg*)my_msg)->lock);
}
printf("thread2:%d\n",((struct msg*)my_msg)->count);
((struct msg *)my_msg)->count ++;
(((struct msg*)my_msg)->flag) = 1;
pthread_mutex_unlock(&((struct msg*)my_msg)->lock);
pthread_cond_signal(&((struct msg *)my_msg)->cond);
printf("thread2 signal!\n");
if(((struct msg *)my_msg)->count >= 9)
{
int err =pthread_join(tid1,NULL);//block
//printf("thread2 pthread_join:%d,%s!\n",err,strerror(err));
printf("thread2 exit!\n");
break;
}
}
return NULL;
}
int main()
{
struct msg my_msg;
init(&my_msg);
pthread_create(&tid1,NULL,thread1_fcn,&my_msg);
pthread_create(&tid2,NULL,thread2_fcn,&my_msg);
// pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return 0;
}
常用的函数和解析
#include <pthread.h> 头文件
int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*func) (void *), void *arg);
pthread_t *tid:线程id的类型为pthread_t,通常为无符号整型,当调用pthread_create成功时,通过*tid指针返回。
const pthread_attr_t *attr:指定创建线程的属性,如线程优先级、初始栈大小、是否为守护进程等。可以使用NULL来使用默认值,通常情况下我们都是使用默认值。
void *(*func) (void *):函数指针func,指定当新的线程创建之后,将执行的函数。
void *arg:线程将执行的函数的参数。如果想传递多个参数,请将它们封装在一个结构体中。
返回值:成功返回0,否则返回一个错误编码。
注:由于多线程的缘故,每个线程都有一个errno 。
打印只需含头文件#include <errno.h> 打印如:printf("%d,%s!\n",err,strerror(err)); //见代码注释
注:联系创建多个线程,不一定先创建的先运行,如此题结果可知,线程2反倒先运行。!
int pthread_join (pthread_t tid, void ** status);
用阻塞自己的方式等待某个线程退出,注意,对于一个线程,不能多次调用,否则返回错误,不成功!
pthread_t tid:要等待的线程ID
void ** status:如果不为NULL,那么线程的返回值存储在status指向的空间中(这就是为什么status是二级指针的原因!这种才参数也称为“值-结果”参数)。
void pthread_exit (void *status);
//线程退出!
void *status:指针线程终止的返回值。
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
pthread_cond_wait() 用于阻塞当前线程,等待别的线程使用pthread_cond_signal()或pthread_cond_broadcast来唤醒它
首先进入wait状态,先unlock,解锁,这样别人才有机会,并把线程放入等待队列,当被唤醒时,重新加锁lock。
int pthread_cond_signal(pthread_cond_t * cond); //个人理解只是发送信号,有内核处理相应的动作,并不会阻塞当前线程,可以看上面结果!