我是靠谱客的博主 追寻篮球,最近开发中收集的这篇文章主要介绍Linux系统编程之线程控制及线程间同步互斥机制:POSIX信号量和互斥锁,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

声明:侵删

文章目录

    • 1. 线程和进程的区别
    • 2.prhread线程库相关API
    • 3.线程间的同步和互斥
    • 4.互斥锁
    • 5.互斥锁例程
    • 6.POISX信号量 [System V 信号量参考此文](https://blog.csdn.net/qq_43921241/article/details/103123667)
    • 7.POSIX信号量例程

1. 线程和进程的区别

进程 :每个进程有自己独立的地址空间
Linux为每个进程创建task_struct (任务结构体,存放进程属性)
每个进程都参与内核调度,不影响其他进程

线程:进程在切换时系统开销大
很多操作系统引入了轻量级进程LWP(线程)
同一进程中的线程共享相同地址空间
Linux不区分进程、线程(Linux都认为成一个任务)
一个进程中的多个线程共享一下资源
线程ID
PC和相关寄存器
堆栈
errno
优先级
执行状态和属性

2.prhread线程库相关API

编译时候要注意链接pthread线程库

线程创建函数:pthread_creat
在这里插入图片描述线程回收函数: pthread_join
在这里插入图片描述线程退出函数:pthread_exit
在这里插入图片描述

3.线程间的同步和互斥

线程共享进程的空间地址和资源,对这些资源进行操作是必须注意线程间的同步和互斥。本文主要介绍POSIX的两种互斥机制: 信号量和互斥锁。
互斥锁适用于同时可用资源唯一的情况,信号量适合于同时可用资源为多个的情况。

4.互斥锁

互斥锁是一种以简单的加锁方式对共享资源的原子操作。互斥锁有两种状态:上锁和解锁。在同一时刻只有一个线程可以掌握互斥锁,拥有上锁状态的线程可以对共享资源进行操作,其余线程想要抢锁就会挂起直到拥有锁的进程释放锁。
互斥锁可以分为快速互斥锁、递归互斥锁、检错互斥锁。
快速锁:调用线程必须堵塞到拥有锁的进程释放锁为止
递归锁:递归锁能够成功的返回,并能增加调用线程在互斥上加锁的次数
检错锁:相当于非堵塞版的快速锁,抢不到锁不会堵塞会返回一个错误信息。
默认是快速互斥锁。
使用互斥锁之前必须初始化锁的类型。
互斥锁相关API

互斥锁初始化函数 pthread_mutex_init
在这里插入图片描述
互斥锁控制函数:上锁、解锁、检查锁、删除锁、
在这里插入图片描述

5.互斥锁例程

/*mutex.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>


#define THREAD_NUM  3 /*线程数*/
#define TASKK_NUM   3  /*每个线程执行的小任务数*/
#define DELAY_TIME  10 /*每个小任务最大时间间隔*/
pthread_mutex_t mutex; /*定义互斥锁*/

/*线程函数*/
void * func_thread(void *arg)
{
    int thread_num = (int) arg;
    int delay_time = 0;
    int count = 0;
    if (pthread_mutex_lock(&mutex) == -1)/*抢锁*/
    {
        perror("pthread_mutex_lock");
        pthread_exit(NULL);
    }
    printf("The thread [%d] is beginningn",thread_num);
    for(count = 0; count<TASKK_NUM;count++)    
    {
        delay_time =(int)(rand()%DELAY_TIME)+1; /*产生随机数1-DLY_TIME*/
        sleep(delay_time);
        printf("tthread[%d],job[%d],sleep[%d]sn",thread_num,count,delay_time);

    }
    printf("pthread[%d] endn",thread_num);
    pthread_mutex_unlock(&mutex);/*解锁*/
    pthread_exit(NULL);
}   
int main()
{
    pthread_t tid[THREAD_NUM];
    int thread_num =0 ;

    srand((time(NULL))); /*初始化随机数种子*/
    pthread_mutex_init(&mutex,NULL);/*初始化互斥锁为快速互斥锁*/

    /*创建线程*/
    for( thread_num=0;thread_num < THREAD_NUM;thread_num ++)
    {
        if (pthread_create(&tid[thread_num],NULL,func_thread,(void *) thread_num) != 0)
        {
            printf("Create pthread[%d]  failedn",thread_num);
            exit(-1);
        }
    }

    printf("Creat all thread sucessed,please waitting ...n" );
    /*回收进程*/
    for(thread_num = 0;thread_num <THREAD_NUM;thread_num++)
    {
        pthread_join(tid[thread_num],NULL);
        printf("thread[%d]  joinedn",thread_num);
    }
    pthread_mutex_destroy(&mutex); /*删除锁*/
    exit(1);


}

结果对比
在这里插入图片描述

6.POISX信号量 System V 信号量参考此文

信号量实质是一个非负整数的计数器,是操作系统中的PV原语,常用于线程间的同步与互斥。
一次 P 操作使信号量sem 减 1, 而一次 V 操作使 sem 加 1。 进程( 线程) 根据信号量的值来判断是否对公共资源具有访问权限。当 sem 的值大于等于 0 时,该进程(或线程)具有公共资源的访问权限;相反,当 sem 的值小于 0 时,该进程(线程)就将阻塞直到 sem 的值大于等于 0 为止。
信号量常用语进程(线程)之间的同步或者互斥
互斥 当信号量作互斥作用时,往往设置一个信号量来决定资源归属
在这里插入图片描述
同步信号量做同步机制时,往往设置多个信号量,通过初始化值和PV操作来决定他们的运行顺序。


POSIX信号量相关API
信号量创建初始化函数 sem_init
在这里插入图片描述
信号量操作函数 PV操作、删除、获取信号量的值
在这里插入图片描述**

7.POSIX信号量例程

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

#define THREAD_NUM  3 /*线程数*/
#define TASKK_NUM   3  /*每个线程执行的小任务数*/
#define DELAY_TIME  10 /*每个小任务最大时间间隔*/


sem_t sem[THREAD_NUM];

/*线程函数*/
void * func_thread(void *arg)
{
    int thread_num = (int) arg;
    int delay_time = 0;
    int count = 0;
    /*每个线程首先进行P操作 ,判断有无资源*/
    sem_wait(&sem[thread_num]);
    printf("The thread [%d] is beginningn",thread_num);
    for(count = 0; count<TASKK_NUM;count++)    
    {
        delay_time =(int)(rand()%DELAY_TIME)+1; /*产生随机数1-DLY_TIME*/
        sleep(delay_time);
        printf("tthread[%d],job[%d],sleep[%d]sn",thread_num,count,delay_time);
    }
    printf("pthread[%d] endn",thread_num);

    pthread_exit(NULL);
}   
int main()
{
    pthread_t tid[THREAD_NUM];
    int thread_num =0 ;

    srand((time(NULL))); /*初始化随机数种子*/


    /*创建线程*/
    for( thread_num=0;thread_num < THREAD_NUM;thread_num ++)
    {
        sem_init(&sem[thread_num],0,0);/*将所有信号量初始化为0*/
        if (pthread_create(&tid[thread_num],NULL,func_thread,(void *) thread_num) != 0)
        {
            printf("Create pthread[%d]  failedn",thread_num);
            exit(-1);
        }
    }
    /*将最后创建的一个进程进行V操作, sem[THREAD_NUM-1]变为1,最后创建的进程先运行*/
    sem_post(&sem[THREAD_NUM-1]);
    printf("Creat all thread sucessed,please waitting ...n" );
    /*回收进程*/
    for(thread_num = THREAD_NUM -1;thread_num >= 0;thread_num --)
    {
        pthread_join(tid[thread_num],NULL);
        printf("thread[%d]  joinedn",thread_num);
        /*每回收一个线程就将下一个要运行线程解开,对上一个信号量V操作*/
        sem_post(&sem[(thread_num+THREAD_NUM-1)%THREAD_NUM]);
    }
    /*删除信号量*/
    for(thread_num = 0;thread_num <THREAD_NUM-1;thread_num++)
    {
        sem_destroy(&sem[thread_num]);
    }
    exit(1);


}

结果
在这里插入图片描述

最后

以上就是追寻篮球为你收集整理的Linux系统编程之线程控制及线程间同步互斥机制:POSIX信号量和互斥锁的全部内容,希望文章能够帮你解决Linux系统编程之线程控制及线程间同步互斥机制:POSIX信号量和互斥锁所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(65)

评论列表共有 0 条评论

立即
投稿
返回
顶部