消息队列2

线程退出
被动退出:int pthread_cancel(pthread_thread);
1功能
当次线程是死循环时,可以调动这个函数主动取消该线程
2返回值
成功返回0,失败返回非零
3参数
thread:要取消线程的TID

void pthread_exit(void *retval);

1功能
线程调用这个函数时,可以主动退出(终止)
它和exit()很像,exit()是终止整个程序,而pthread_exit是终止次线程。
如果你在次线程里面调用错误,调用的是exit,整个线程就终止了
2返回值
成功返回0,失败返回非零值
3参数
Retval:线程结束的返回值,
如果返回值很多时,就会封装成一个结构体,返回结构体变量的地址即可。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<string.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/types.h>

int num=5;
void *thread1(void *arg)
{    while(1)
    {
sleep(1);
printf(“hellow”);
    pthread_exit(NULL);
    //return (void *)0;
    }
}

int main()
{
    pthread_t id;
    if(pthread_create(&id,NULL, thread1 ,NULL)!=0)
    {
   	perror("pthread_create error");
	exit(1);
    }
   sleep(1);
   int *num;
   pthread_cancel(id);
   pthread_join(id,NULL);

   printf("thread is exit:%d\n",*((int *)num));
    return 0;
}
   void pthread_cleanup_push(void (*routine)(void *), void *arg);
   void pthread_cleanup_pop(int execute);

弹栈线程退出处理函数的几种条件

pthread_cleanup_push(!0)主动弹栈 0不弹出调用

如果线程是被被人调用pthread_cancel取消的,也会弹栈
如果调用pthread exit函数也是会主动弹栈

注意:return退出的话是不会自动弹栈的,想要自动弹栈用pthread_cleanup_pop(10)

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<string.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/types.h>

int num=5;

void thread_exit(void *arg)
{
    printf("my exit\n");
}
void *thread1(void *arg)
{   
    pthread_cleanup_push(thread_exit,NULL);
    while(1)
    {
    sleep(1);
    printf("hello\n ");
    pthread_exit(NULL);
    //return (void *)0;
    }
    pthread_cleanup_pop(!0);
}

int main()
{
    pthread_t id;
    if(pthread_create(&id,NULL, thread1 ,NULL)!=0)
    {
   	perror("pthread_create error");
	exit(1);
    }
   sleep(1);
   int *num;
   pthread_cancel(id);
   pthread_join(id,NULL);

   printf("thread is exit:%d\n",*((int *)num));
    return 0;
}

线程等待的目的:
保证线程的退出顺序:保证一个线程推出并回收资源后允许下一个进程退出
回收线程退出时的资源情况:保证当前线程退出后,创建的新线程不会复用刚才退出线程的地址空间
获得新线程退出时的结果是否正确退出返回值

线程的状态
可结合态:这种状态下的线程是能被其他进程回收资源或被杀死的
可分离态:不能被其他资源或被杀死的,他储存的资源在他的终止时由i系统自动回收
默认情况下,线程可结合态

线程分离函数
pthread_detach()
int pthread_detach(pthread_t thread);

功能:如果次线程不希望别人调用pthread_join函数来回收,而是希望自己在运行结束时,自动回收资源调用pthread_detach将pthread_detach()种的线程变为分离态
2返回值:成功返回0,错误返回一个错误的数字
3参数:thread:你要分离的那个次线程的TID

Tach_struct 进程id
进程所有的优先级 地址空间

线程开销低:实质上是函数的切换

线程同步:互斥锁,线程信号量,条件变量

互斥锁:
1定义一个互斥锁(变量) pthread_mutex_t mutex;
2初始化锁:预设互斥锁的初始值 pthread_mutex = PTHREAD_MUTEX_INITIALIZER(不常用)
Int respthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t * restrict attr)

功能
初始化定义的互斥锁(就是设置互斥锁所需的值)
返回值:总是返回0,所以这个函数不需要错误处理
参数:
mutex:互斥锁,需要我们自己定义
3 加锁解锁
pthread_mutex_lock()
pthread_mutex_trylock() 非阻塞加锁 当锁被占用时 返回EBUSY而不是挂起等待
pthread_mutex_unlock()

4进程退出时销毁互斥锁

线程信号量:
线程信号量使用步骤:
1定义信号量集合
sem_t sem[3]
线程信号量集合其实就是一个数组,数组的每个元素就是一个信号量
(sem[0]:第一个信号量)
(sem[1]:第二个信号量)
(sem[2]:第三个信号量)

2初始化集合中的每个信号量

#inlcude<semaphore.h>
Int sem_init(sem_t *sem,int pthread,unsigned int value)
功能:
初始化线程信号量集合中的某个信号量,给它一个初值
返回值:
成功返回0,失败返回-1,errno被设置
信号量的错误号不是返回的,而是直接设置到errno value:初始化值(对于二进制信号量来说,要么是1,要么是0)
Pshared:0 给线程使用,!0可以给进程使用

3 p、v 操作
P操作 int sem_wait(sem_t *sem);

( 了解 int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);)

V:操作(不存在阻塞的问题)
Int sem_post(sem_t *sem);

sem_wait value
假如你获得的时候别人已经获得了这个信号量(value值减一),你阻塞

#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<stdlib.h>
#include <semaphore.h>

#define MAX_SIZE 1024
#define FIFO "./test3.txt"

sem_t sem[3];
char buffer[MAX_SIZE];

struct message
{

    int fd;
};

 pthread_mutex_t mutex;

void *thread1(void *arg)
{
    struct message msg= *((struct message *)arg);
    int  fd =msg.fd;
       while(1)
       {
	  // pthread_mutex_lock(&mutex);
	  sem_wait(&sem[0]);
	   write(fd,"world",5);
	   write(fd,"hello\n",6);
	   pthread_mutex_unlock(&mutex);
	   sem_post(&sem[0]);
       }
}

void *thread2(void *arg)
{
    struct message msg= *((struct message *)arg);
    int  fd =msg.fd;
       while(1)
       {
	  sem_wait(&sem[0]);
	   //pthread_mutex_lock(&mutex);
	   write(fd,"hhhhh",5);
	   write(fd,"wwwww\n",6);  
	  // pthread_mutex_unlock(&mutex);
	   sem_post(&sem[0]);
       }
}

int main()
{
    pthread_t id1;

    struct message msg;

    int fd1;

    int fd = open(FIFO,O_RDWR|O_CREAT|O_APPEND,0666);
    if(fd<0)
    {
	perror("open file error");
	exit(1);
    }


    msg.fd=fd;
    pthread_mutex_init(&mutex,NULL);

    if(0 != pthread_create(&id1,NULL, thread1 ,(void *)(&msg)))
    {
	perror("pthread_create error");
	exit(1);
    }

    pthread_t id2;
    if(0 != pthread_create(&id2, NULL, thread2 ,(void *)(&msg)))
    {
	perror("pthread_create error");
	exit(1);
    }

   // pthread_join(&id1,NULL);
   // pthread_join(&id2,NULL);
    
    pause();
    return 0;
}

4 进程结束时,删除线程信号量的集合

条件变量(和互斥锁配合使用)
一条线程做自加,一条线程输出(当自加到5的时候输出,之后自加变量清零)
条件变量的主要作用(线程协同):主线程对count+1.,次线程发现当count==5时输出count的值并将count清零。

多线程配合工作时,当线程检测到某条件不满足时就休眠,直到别的线程将条件准备好,然后通过条件变量将其叫醒。

使用步骤
1定义一个条件变量
pthread_cond_t
2初始化
pthread_cond_init(pthread_cond_t *restrict cond ,const pthread_condattr_t *restrict attr);
功能
初始化条件变量,与互斥锁类似
pthread_cond_t cond = PTHREAD COND INITIALIZER
返回值:
成功返回0,
3使用条件变量
4删除条件变量,也需要把互斥锁删除

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>

int count = 0;
pthread_mutex_t mutex;
pthread_cond_t cond;

void *add_l(void *arg)
{
    while(1)
    {
	pthread_mutex_lock(&mutex);
	count++;
	if(count==5)
	{
	    pthread_cond_signal(&cond);
	}
	sleep(1);
	pthread_mutex_unlock(&mutex);
	sleep(1);
    }
}

void *print(void *arg)
{
    while(1)
    {
	pthread_mutex_lock(&mutex);
	if(count!=5)
	{
	    pthread_cond_wait(&cond,&mutex);
	}
	else
	{
	    printf("count = %d\n",count);
	    count = 0;
	}
        sleep(1);
	pthread_mutex_unlock(&mutex);
       	sleep(1);
    }
}
int main()
{

    pthread_t id1;
    pthread_t id2;

    int ret;
    pthread_mutex_init(&mutex,NULL);
    pthread_cond_init(&cond,NULL);

    ret=pthread_create(&id1,NULL,add_l,NULL);
    if(ret!=0)
    {
	perror("error");
	exit(0);
    }
    
    
    ret=pthread_create(&id2,NULL,print,NULL);
    if(ret!=0)
    {
	perror("error");
	exit(0);
    }
    pthread_join(id1,NULL);
    pthread_join(id2,NULL);
   
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

躺尸研究员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值