linux线程锁、消费者生产者

一、创建线程

函数

  • pthread_self()
    • 获取线程ID。其作用对应进程中 getpid() 函数。
    • 成功: 0 失败: 无
  • pthread_create()
    • 创建一个新线程。 对应进程中 fork() 函数。
    • int pthread_create(phtread_t *thread, const pthread_attr, void *( *start_routine)(void *), void *arg);
    • 返回值
      • 成功:0
      • 失败:错误号
    • 参数:
      • 参数一:传出参数,保存系统为我们分配好的线程ID
      • 参数二:通常传NULL,表示使用线程默认属性。若想使用具体属性也可以修改该参数。
      • 参数三:函数指针,指向线程主函数,该函数运行结束,则线程结束。
      • 参数四:线程主函数执行期间所使用的参数。

实现

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

void *tfn(void *arg){
    
    //线程id    用来在进程当中标识线程身份。
    printf("thread: pid = %d, tid = %lu\n", getpid(), pthread_self());
    
    return NULL;
}

int main(int argc, char *argv[]){
    
    pthread_t tid;
    
    printf("main: pid = %d, tid = %lu\n", getpid(), pthread_self());
    
    int ret = pthread_create(&tid, NULL, tfn, NULL);
    if(ret != 0){
        perror("pthread_create error");
    }
    
    //确保子线程创建完之前,主线程没有结束
    sleep(1);
    
    return 0;
}

现象
在这里插入图片描述





二、使用互斥锁使共享数据同步

同步即协同步调,按预定的先后次序运行。

在没有加锁之前

由于共享、竞争而没有加任何同步机制,导致产生于时间有关的错误,造成数据混乱。

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

void *tfn(void *arg){
    srand(time(NULL));
    
    while(1) {
        printf("hello---");
        sleep(rand() % 3);  //模拟长时间操作共享资源,导致cpu易主,产生与时间有关的错误
        printf("---word\n");
        sleep(rand() % 3);
    }
	
    return NULL;
}


int main(void){
    
    pthread_t tid;
    srand(time(NULL));
    
    pthread_create(&tid, NULL, tfn, NULL);
    while(1) {
        printf("HELLO====");
        sleep(rand() % 3);
        printf("===WORLD\n");
        sleep(rand() % 3);
    }
    
    pthread_join(tid, NULL);
    
    return 0;
}

现象
在这里插入图片描述



加锁之后

使用mutex(互斥量、互斥锁)一般步骤:

  • pthread_mutex lock; 创建锁
  • pthread_mutex_init; 初始化
  • pthread_mutex_lock; 加锁
  • 访问共享数据(stdout)
  • pthrad_mutex_unlock(); 解锁
  • pthread_mutex_destroy(); 销毁锁
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>
#include<unistd.h>

pthread_mutex_t mutex;   //1、定义一把互斥锁

void *tfn(void *arg){
    srand(time(NULL));
    
    while(1) {
        pthread_mutex_lock(&mutex);   //加锁
        printf("hello---");
        sleep(rand() % 3);   //模拟长时间操作共享资源,导致cpu易主,产生与时间有关的错误
        printf("---word\n");
        pthread_mutex_unlock(&mutex);  //解锁
        
        sleep(rand() % 3);
    }
    
    return NULL;
}


int main(void){
    pthread_t tid;
    srand(time(NULL));
    
    int ret = pthread_mutex_init(&mutex, NULL);  //2.初始化
    if(ret != 0){
        fprintf(stderr, "mutex init error:%s\n", strerror(ret));
        exit(1);
    }
    
    pthread_create(&tid, NULL, tfn, NULL);
    while(1) {
        pthread_mutex_lock(&mutex);   //加锁
        printf("HELLO====");
        sleep(rand() % 3);
        printf("====WORLD\n");
        pthread_mutex_unlock(&mutex);  //解锁
        
        sleep(rand() % 3); 
    }
    
    pthread_join(tid, NULL);
    
    phtread_mutex_destroy(&mutex);  //6.销毁互斥锁
    
    return 0;
      
}

现象
在这里插入图片描述



三、生产者消费者


生产者:

  • 生产数据
  • 加锁 pthread_mutex_lock(&mutex)
  • 将数据放置到 公共区域
  • 解锁 pthread_mutex_unlock(&mutex)
  • 通知阻塞在条件变量上的线程
    • pthread_cond_signal()
    • pthread_cond_broadcast()
  • 循环生产后续数据
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<pthread.h>

void err_thread(int ret, char *str){
    
    if(ret != 0){
        fprintf(stderr, "%s:%s\n", str, strerror(ret));
        pthread_exit(NULL);
    }
}

struct msg{   //定义公共变量
    int num;
    struct msg *next;
};

struct msg *head;  //头指针

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  //互斥量
pthread_cond_t has_data = PTHREAD_COND_INITIALIZER;  //条件变量

void *produser(void *arg){
    
    while(1){
        struct msg *mp = malloc(sizeof(struct msg));
        
        mp->num = rand() % 1000;
        printf("----produce %d\n", mp->num);
        
        pthread_mutex_lock(&mutex);  //加锁
        mp->next = head;   //写数据
        head = mp;
        pthread_mutex_unlock(&mutex);
        
        pthread_cond_signal(&has_data);  //唤醒阻塞在条件变量 has_data 上的线程
        
        sleep(rand() % 3);
        
    }
    
    return NULL;
}


void *consumer(void *arg){
    
    while(1){
        struct msg *mp;
        
        pthread_mutex_lock(&mutex);  //加锁 互斥量
        if(head == NULL){
            pthread_cond_wait(&has_data, &mutex);  //阻塞等待条件变量解锁后,pthread_cond_wait 返回时,重新加锁 mutex
        }
        
        mp = head;
        head = mp->next;
        
        pthread_mutex_unlock(&mutex);  //解锁
        printf("++++consumer: %d\n", mp->num);
        
        free(mp);
        sleep(rand() % 3);
    }
    
    return NULL;
}

int main(int argc, char *argv[]){
    
    int ret;
    pthread_t pid, cid;
    
    srand(time(NULL));
    
    ret = pthread_create(&pid, NULL, produser, NULL);  //生产者
    if(ret != 0){
        err_thread(ret, "pthread_create produser error");
    }
    
    ret = pthread_create(&cid, NULL, consumer, NULL);  //消费者
    if(ret != 0){
        err_thread(ret, "pthread_create consumer error");
    }
    
    pthread_join(pid, NULL);
    pthread_join(cid, NULL);
    
    return 0;
}

现象
在这里插入图片描述

  • 30
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值