条件变量和信号量

1.pthread
./pthread &显示进程号
在这里插入图片描述

ps 查看进程号
ps -T 查看线程号

也可以进入进程的proc目录查看线程
在这里插入图片描述

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>

static char g_buf[1000];
static sem_t g_sem;
static void *my_thread_func (void *data)
{
        while (1)
        {
                //sleep(1);
                /* 等待通知 */
                //while (g_hasData == 0);
                sem_wait(&g_sem);

                /* 打印 */
                printf("recv: %s\n", g_buf);
        }

        return NULL;
}


int main(int argc, char **argv)
{
        pthread_t tid;
        int ret;

        sem_init(&g_sem, 0, 0);

        /* 1. 创建"接收线程" */
        ret = pthread_create(&tid, NULL, my_thread_func, NULL);
        if (ret)
        {
                printf("pthread_create err!\n");
                return -1;
        }


        /* 2. 主线程读取标准输入, 发给"接收线程" */
        while (1)
        {
                fgets(g_buf, 1000, stdin);

                /* 通知接收线程 */
                sem_post(&g_sem);
        }
        return 0;
}

通过上述例程可以发现,多次执行该函数其次序是无序的,线程之间的竞争无法控制,通过使用信号量来使得线程顺序为可控的。
为了解决上述对临界资源的竞争问题,pthread线程引出了互斥锁来解决临界资源访问。通过对临界资源加锁来保护资源只被单个线程操作,待操作结束后解锁,其余线程才可获得操作权。

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <semaphore.h>

char getbuf[128] = {0};
static sem_t g_sem;/* 定义信号量 */
pthread_mutex_t mutex;/* 定义互斥锁 */

static void *WorkProduct(void *data)
{
          pthread_mutex_lock(&mutex);



         strcpy(getbuf, "data");
           pthread_mutex_unlock(&mutex);
            sem_post(&g_sem);
              pthread_exit(NULL);/* 必须线程退出否则打印不出data */


}
static void *WorkConsume(void *data)
{

                sem_wait(&g_sem);
                printf("%s\n",getbuf);
                pthread_exit(NULL);/* 必须线程退出否则打印不出data */

}

int main(int argc, char **argv)
{
        pthread_t tid, dit;
        sem_init(&g_sem, 0, 0);
        pthread_mutex_init(&mutex, NULL);
        pthread_create(&tid, NULL, WorkProduct, NULL);
         pthread_create(&dit, NULL, WorkConsume, NULL);

         pthread_join(tid,NULL);
         pthread_join(dit,NULL);

         return 0;
}

线程的退出与回收
线程的退出情况有三种:第一种是进程结束,进程中所有的线程也会随之结束。第二种是通过函数pthread_exit来主动的退出线程。第三种被其他线程调用pthread_cancel来被动退出。
当线程结束后,主线程可以通过函数pthread_join/pthread_tryjoin_np来回收线程的资源,并且获得线程结束后需要返回的数据。

  1. 线程主动退出
    pthread_exit函数原型如下:
    线程主动退出
#include <pthread.h>
void pthread_exit(void *retval);

pthread_exit函数为线程退出函数,在退出时候可以传递一个void*类型的数据带给主线程,若选择不传出数据,可将参数填充为NULL。

  1. 线程被动退出
    pthread_cancel函数原型如下:
    线程被动退出,其他线程使用该函数让另一个线程退出
#include <pthread.h>
int pthread_cancel(pthread_t thread);

成功:返回0
该函数传入一个tid号,会强制退出该tid所指向的线程,若成功执行会返回0。

  1. 线程资源回收(阻塞方式)
    pthread_join函数原型如下:
    线程资源回收(阻塞)
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);

该函数为线程回收函数,默认状态为阻塞状态,直到成功回收线程后才返回。第一个参数为要回收线程的tid号,第二个参数为线程回收后接受线程传出的数据。

  1. 线程资源回收(非阻塞方式)
    pthread_tryjoin_np函数原型如下:
    线程资源回收(非阻塞)
#define _GNU_SOURCE            
#include <pthread.h>
int pthread_tryjoin_np(pthread_t thread, void **retval);

该函数为非阻塞模式回收函数,通过返回值判断是否回收掉线程,成功回收则返回。

条件变量
条件变量时一种同步机制,用来通知其他线程条件满足了。一般是用来通知对方共享数据的状态信息,因此条件变量时结合互斥量来使用的。
创建和销毁条件变量
函数原型如下:
#include <pthread.h>
// 初始化条件变量

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);//cond_attr

通常为NULL

// 销毁条件变量

int pthread_cond_destroy(pthread_cond_t *cond);

这些函数成功时都返回0
等待条件变量
函数原型如下:

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

这需要结合互斥量一起使用,示例代码如下:

pthread_mutex_lock(&g_tMutex);
pthread_cond_wait(&g_tConVar, &g_tMutex);  // 如果条件不满足则,会unlock g_tMutex
                                           // 条件满足后被唤醒,会lock g_tMutex

/* 操作临界资源 */

pthread_mutex_unlock(&g_tMutex);

通知条件变量
函数原型如下:

int pthread_cond_signal(pthread_cond_t *cond);

p

thread_cond_signal函数只会唤醒一个等待cond条件变量的线程,示例代码如下:
pthread_cond_signal(&g_tConVar);

条件变量模拟信号量

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/syscall.h>

#define BUFSIZE 128
char data[]="This is data";
char buf[BUFSIZE]= {0};
pthread_mutex_t mutex;//定义互斥锁
pthread_cond_t cond1;//定义条件变量
pthread_cond_t cond2;//定义条件变量


void *WorkProduct(void *arg)
{
  printf("This is product\n");
  while(1)
  {
    
    pthread_mutex_lock(&mutex);
    while(buf[0] != 0)  /* 如果有数据 */
    {
      pthread_cond_wait(&cond2,&mutex);//获得互斥量后判断条件是否成立,没有成立释放互斥量,一旦返回就表示条件成立并且就会获得互斥量
  }
    
    strncpy(buf,data,sizeof(data)); //生产数据
   

    pthread_cond_signal(&cond1);//通知消费者条件成立了
    pthread_mutex_unlock(&mutex);//释放锁
    sleep(1);
  }
  return NULL;
}

void *WorkConsume(void *arg)
{
   printf("This is consume\n");
  while(1)
  {
    pthread_mutex_lock(&mutex);
    while( 0== buf[0])
    {
      pthread_cond_wait(&cond1,&mutex);
    }

    memset(&buf[0],0,sizeof(buf));//消耗数据
    
    pthread_cond_signal(&cond2);//通知生产者条件成立了
    pthread_mutex_unlock(&mutex);//释放锁
    sleep(1);
  }
  return NULL;
}

int main()
{
     pthread_t cons,prod;
     pthread_mutex_init(&mutex,NULL);//互斥锁初始化
     pthread_cond_init(&cond1,NULL);//条件变量初始化
     pthread_cond_init(&cond2,NULL);//条件变量初始化
    
  

    pthread_create(&prod,NULL,WorkProduct,NULL);
    pthread_create(&cons,NULL,WorkConsume,NULL);

  
    pthread_join(cons,NULL);//线程等待
    pthread_join(prod,NULL);
  

    pthread_mutex_destroy(&mutex);//销毁互斥锁
    pthread_cond_destroy(&cond1);
    pthread_cond_destroy(&cond2);


     return 0;
     }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

吴凯你在想啥呢

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

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

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

打赏作者

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

抵扣说明:

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

余额充值