目录
概念
线程与进程的区别
进程是程序执行的实例,进程是线程的容器,一个进程中的多个线程共用一个地址空间
进程之间拥有自己独立的内存空间,一个进程死掉后不会对其他进程产生影响,而线程只有自己的堆栈和局部变量的地址空间,一个线程死掉对于整个线程死掉。
进程间通讯不方便需要进行通道或者其他特定的通讯方式,而线程拥有共享内存,改变共享内存可以达到线程间通讯的效果
操作
操作部分有为三个大点:1.线程创建、退出、等待、获取id、判断
2.线程的互斥锁应用
3.线程条件下等待和触发
线程创建、退出、等待、获取id、判断
线程部分api都需要包括头文件include<pthread.h>
线程创建:
int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void*(*start_rtn)(void*),void*restrict arg);
第一个参数tidp需要我们传一个pthread_t类型的地址进去,然后该函数会将生成的线程id存放入里面。
第二个参数是线程属性,一般为NULL即可
第三个参数为线程运行函数的函数指针
第四个参数为传入创建线程的参数的地址,一个参数既取变量地址即可,多个参数可以将其变为结构体或字符串等再将其地址传入。
线程退出
int pthread_exit(void* rval_ptr);
变量rval_ptr是线程退出(结束)后传回的参数,在线程等待的api中接收转存
线程等待
int pthread_join(pthread_t thread,void **rval_ptr);
第一个参数为等待退出线程的id,是线程创建时的第一个参数。
第二个参数是接收线程退出时传回来的参数。
线程获取id
pthread_t pthread_self(void)
返回当前线程的id
线程比较
因为线程id在不同操作系统有不同的表现形式,所以不能当做一个配套整形来比较,所以特别编写了一个api来比较线程id
int pthread_equal(pthread_t tid1,pthread_t pid2);
实际运用
思路:首先在main函数中我们创建线程函数func1,并传入参数arg,然后等待线程结束
在线程中打印main中传进来的arg以及线程id,然后结束线程并回传参数ret。
#include <stdio.h>
#include <pthread.h>
void *func1(void *arg)
{
static int ret = 10;
printf("t1:%ld thread is create\n",(unsigned long)pthread_self());
printf("t1:param = %d\n",*((int*)arg));
pthread_exit((void*)&ret);
}
int main(void)
{
pthread_t t1;
int param = 100;
int *Thread;
int ret;
ret = pthread_create(&t1,NULL,func1,(void*)¶m);
pthread_join(t1,(void **)&Thread);
printf("pr:%ld thread is create\n",(unsigned long)pthread_self());
printf("pr:Thread = %d\n",*Thread);
return 0;
}
线程的互斥锁应用
创建互斥锁
int pthread_mutex_inti(pthread_mutex_t *restrict mutex,const pthread_mutex_attr_t *restrict attr)
第一个参数是创建的互斥锁id的存放地址
第二个参数是互斥锁属性一般为NULL
销毁互斥锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
参数是要关闭的互斥锁id
加锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
参数是要关闭的互斥锁id
解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
参数是要关闭的互斥锁id
实际运用
线程1和线程2交替增加全局变量,但要求全局变量增加为3的操作一定为线程1的操作,即可用互斥锁来实现
因为系统不能确定线程1线程2哪个先运行所以我们用互斥锁来规范运行次序,而且当线程二先运行时,我们运行一次就开关一次互斥锁,则线程1就可以达到我们需要的效果。
#include <stdio.h>
#include <pthread.h>
int p_data=0;
pthread_mutex_t mutex;
void *func1(void *arg)
{
//加锁,相当于取钥匙开锁,如果其他线程未将钥匙放回来,则死等
pthread_mutex_lock(&mutex);
while(1)
{
printf("t1:%d\n",p_data++);
sleep(1);
if(p_data == 3)
{
printf("succes=========================================================//\n");
pthread_mutex_unlock(&mutex); //开锁,相当于将钥匙放回来
pthread_exit(NULL); //退出线程
}
}
}
void *func2(void *arg)
{
//该线程中加一次全局变量开一次锁,所以不管第一次是线程1开锁还是线程2开锁,第三次一定的线程1累加到的,因为线程二加完一次就跳到线程1一直加到pdata=3.
while(1)
{
pthread_mutex_lock(&mutex);
printf("t2:%d\n",p_data++);
sleep(1);
pthread_mutex_unlock(&mutex);
}
}
int main(void)
{
pthread_t t1,t2;
int param = 100;
int *Thread;
int ret;
pthread_mutex_init(&mutex,NULL);
ret = pthread_create(&t1,NULL,func1,(void*)¶m);
ret = pthread_create(&t2,NULL,func2,(void*)¶m);
while(1)
{
printf("main:%d\n",p_data);
sleep(1);
pthread_mutex_destroy(&mutex);
}
return 0;
}
线程条件下等待和触发
线程等待
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t*restrict mutex);
第一个参数是pthread_cond_t类型的线程条件变量,第二个参数是线程的互斥锁id
等待触发
int pthread_cond_signal(&cond)
创建条件
pthread_cond_init(&cond,NULL);
销毁条件
pthread_cond_destroy(&cond);
实际应用
在线程2中加入条件则在条件成立时cond运行
而cond在线程1中等待条件成立
#include <stdio.h>
#include <pthread.h>
int p_data=0;
pthread_mutex_t mutex;
pthread_cond_t cond;
void *func1(void *arg)
{
while(1)
{
pthread_cond_wait(&cond,&mutex);
printf("t1:%d\n",p_data++);
sleep(1);
printf("succes=========================================================//\n");
// pthread_exit(NULL);
exit(0);
}
}
void *func2(void *arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
printf("t2:%d\n",p_data++);
if(p_data == 3)
{
pthread_cond_signal(&cond);
}
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
int main(void)
{
pthread_t t1,t2;
int param = 100;
int *Thread;
int ret;
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
ret = pthread_create(&t1,NULL,func1,(void*)¶m);
ret = pthread_create(&t2,NULL,func2,(void*)¶m);
// printf("main:%d\n",p_data);
sleep(1);
pthread_join(t2,NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
}
线程的锁和cond的初始化宏
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALQER;
pthread_cond_t cond = PTHREAD_COND_INITIALQER;