线程的互斥锁(代码片段)

xiehuan-blog xiehuan-blog     2023-01-02     561

关键词:

一、竞争与同步
当多个线程同时访问其所共享的进程资源时,需要相互协调,以防止出现数据不一致、不完整的问题。这就叫线程同步。

二、互斥量

int pthread_mutex_init (pthread_mutex_t* mutex,const pthread_mutexattr_t* mutexattr);
功能:初始化互斥量
//亦可 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
?
int pthread_mutex_lock (pthread_mutex_t* mutex);
功能:加锁
?
int pthread_mutex_unlock (pthread_mutex_t* mutex);
功能:解锁
?
int pthread_mutex_destroy (pthread_mutex_t* mutex);
功能:销毁互斥量

1) 互斥量被初始化为非锁定状态;
2) 线程1调用pthread_mutex_lock函数,立即返回,互斥量呈锁定状态;
3) 线程2调用pthread_mutex_lock函数,阻塞等待;
4) 线程1调用pthread_mutex_unlock函数,互斥量呈非锁定状态;
5) 线程2被唤醒,从pthread_mutex_lock函数中返回,互斥量呈锁定状态;

三、信号量
信号量是一个计数器,用于控制访问有限共享资源的线程数。
注意:线程使用的信号量不在pthread.h中,而是semaphore.h

// 创建信号量
int sem_init (sem_t* sem, int pshared,unsigned int value);

 sem           信号量ID,输出。
?pshared   一般取0,表示调用进程的信号量。非0表示该信号量可以共享内存的方式,为多个进程所共享(Linux暂不支持)。
 value    信号量初值。
?
// 信号量减1,不够减即阻塞
int sem_wait (sem_t* sem);
?
// 信号量减1,不够减即返回-1,errno为EAGAIN
int sem_trywait (sem_t* sem);
?
// 信号量减1,不够减即阻塞,直到abs_timeout超时返回-1,errno为ETIMEDOUT

int sem_timedwait (sem_t* sem,const struct timespec* abs_timeout);
struct timespec
    time_t tv_sec;  // Seconds
    long   tv_nsec; // Nanoseconds [0 - 999999999]
;
?
// 信号量加1
int sem_post (sem_t* sem);
?
// 销毁信号量
int sem_destroy (sem_t* sem);

 

//简单的图书借阅小程序
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <stdlib.h>
#include <time.h>

sem_t sem;
void* fun(void* arg)

    pthread_t tid = pthread_self();
    int* sec = arg;
    printf("请等待(%lu)...
",tid);
    sem_wait(&sem);
    printf("借阅成功(%lu),正在读书,读书时间为:%d秒
",tid,*sec);
    sleep(*sec);
    sem_post(&sem);
    printf("还书成功(%lu)!
",tid);



int main()

    srand((int)time(NULL));
    pthread_t thread;
    sem_init(&sem,0,5);

    for(int i=0; i<20; i++)
    
        int time = rand()%10;
        int ret = pthread_create(&thread,NULL,fun,&time);
        if(ret < 0)
        
            perror("pthread_create");
            return -1;
        
        sleep(1);
    
    
    sem_destroy(&sem);
    while(1);        //主线程不结束
    

 

四、生产者与消费者模型
一线程负责生产数据,另一部分线程负责消费数据。
问题1:如何生产的快、消费的慢,生产者容易撑死
问题2:如果生产的慢、消费的快,消费者容易饿死
只有把问题1、和问题2协调好,才能最大限度的提高效率。

生产者快->数据池满->生产者暂停->消费者全部开始消费->数据池空->消费者暂停->生产者全部开始生产

五、条件变量
条件变量可以让调用线程在满足特定条件的情况下暂停。

//初始化条件变量
int pthread_cond_init (pthread_cond_t* cond,const pthread_condattr_t* attr);
//亦可pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
?
// 使调用线程睡入条件变量cond,同时释放互斥锁mutex
int pthread_cond_wait (pthread_cond_t* cond,pthread_mutex_t* mutex);
?
// 使调用线程睡入条件变量cond,同时释放互斥锁mutex,并在时间到了之后即使没有被唤醒,也醒过来
int pthread_cond_timedwait (pthread_cond_t* cond,
    pthread_mutex_t* mutex,
    const struct timespec* abstime);
?
struct timespec
    time_t tv_sec;  // Seconds
    long   tv_nsec; // Nanoseconds [0 - 999999999]
;
?
// 从条件变量cond中唤出一个线程,令其重新获得原先的互斥锁
int pthread_cond_signal (pthread_cond_t* cond);
注意:被唤出的线程此刻将从pthread_cond_wait函数中返回,
但如果该线程无法获得原先的锁,则会继续阻塞在加锁上。
?
// 从条件变量cond中唤出所有线程
int pthread_cond_broadcast (pthread_cond_t* cond);
?
// 销毁条件变量
int pthread_cond_destroy (pthread_cond_t* cond);

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

#define MAX 20

char storage[MAX] = ;
int count = 0;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t full = PTHREAD_COND_INITIALIZER;
pthread_cond_t empty = PTHREAD_COND_INITIALIZER;

void show_storage(char* role,char* op,char prod)

    printf("%s:",role);
    for(int i=0; i<count; i++)
    
        printf("%c",storage[i]);
    
    printf("%s%c
",op,prod);


void* pro_run(void* arg)

    char* who = "生产者";
    while(1)
    
        pthread_mutex_lock(&mutex);
        while(count >= MAX)
        
            printf("%s:满仓
",who);
            pthread_cond_wait(&full,&mutex);
        

        char prod = A+rand()%26;
        storage[count++] = prod;

        show_storage(who,"->",prod);
        
        pthread_cond_signal(&empty);
        pthread_mutex_unlock(&mutex);
        
        usleep(rand()%100*1000);
    


void* con_run(void* arg)

    char* who = "消费者";
    while(1)
    
        pthread_mutex_lock(&mutex);
        while(count <= 0)
        
            printf("%s:空仓
",who);
            pthread_cond_wait(&empty,&mutex);
        

        char prod = storage[count--];

        show_storage(who,"<-",prod);
        
        pthread_cond_signal(&full);
        pthread_mutex_unlock(&mutex);
        
        usleep(rand()%100*1000);
    


int main()

    pthread_t tid1,tid2;
    pthread_create(&tid1,NULL,pro_run,NULL);
    pthread_create(&tid2,NULL,con_run,NULL);
    getchar();

 

















































































线程的互斥锁(代码片段)

一、竞争与同步 当多个线程同时访问其所共享的进程资源时,需要相互协调,以防止出现数据不一致、不完整的问题。这就叫线程同步。 二、互斥量 intpthread_mutex_init(pthread_mutex_t*mutex,constpthread_mutexattr_t*mutexattr); 功能:初始化互... 查看详情

rtx线程通信之——互斥锁(代码片段)

文章目录Mutex概念RTX互斥锁API互斥锁使用步骤小结参考资料Mutex互斥锁(Mutex)是线程间实现资源同步的重要机制之一。概念Mutexstandsfor“MutualExclusion”.Inreality,amutexisaspecializedversionofsemaphore.Mutualexclusion(widelyknownasMutex)is 查看详情

多线程互斥锁读写锁(代码片段)

/*Linux环境编程:从应用到内核*//*0.4.3线程安全线程安全,顾名思义是指代码可以在多线程环境下“安全”地执行。何为安全?即符合正确的逻辑结果,是程序员期望的正常执行结果。为了实现线程安全,该代码要么只能使... 查看详情

linux互斥锁(代码片段)

互斥的概念在多线程编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为"互斥锁"的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。互斥锁操... 查看详情

python线程互斥锁lock(代码片段)

目录一.前言二.Python线程共享全局变量三.Python线程互斥锁1.创建互斥锁2.锁定资源/解锁资源四.Python线程死锁五.重点总结六.猜你喜欢一.前言在前一篇文章Python线程创建和传参中我们介绍了关于Python线程的一些简单函数使用和线程... 查看详情

synchronized互斥锁实例解析(代码片段)

...synchronized互斥锁实例解析1、互斥锁基础使用:防止多个线程访问对象的synchronized方法。1.1、不加互斥锁时1.2、加互斥锁后2、脏读2.1、不加锁2.2、加锁后java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置... 查看详情

互斥锁mutex的使用(代码片段)

...)throwex;finallymutex.ReleaseMutex();1、initiallyOwned表示创建mutex的线程是否拥有该互斥体。true表示创建线程拥有互斥锁,只有在创建线程中调用ReleaseMutex释放后,其他等待线程才能参与抢夺互斥体的活动。false表示互斥锁体于与空闲状态... 查看详情

互斥锁(代码片段)

当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。互斥锁为资源引入一个状态:锁定/非锁定某个线程要更改共享数据时,先将... 查看详情

互斥锁,信号量,条件变量,读写锁(代码片段)

互斥锁互斥锁的特性:1.原子性:当有一个线程成功拿到了这个锁,其他线程都无法在相同的时间拿到这个锁2.唯一性:在一个线程拿到锁的这段时间,只有当这个线程把锁释放掉,其他的线程才有可能拿到3.非繁忙等待性:如果... 查看详情

[c++11多线程同步]---互斥锁(代码片段)

1四种互斥锁在C++11中一共提供了四种互斥锁:std::mutex:独占的互斥锁,不能递归使用std::timed_mutex:带超时的独占互斥锁,不能递归使用std::recursive_mutex:递归互斥锁,不带超时功能std::recursive_time... 查看详情

并发编程线程互斥(代码片段)

线程互斥该实例创建了3个线程t1、t2和t3同步执行,三个线程都访问全局变量data,并改变它的值。当第一个线程t1请求锁成功后,开始访问共享数据data,第二个线程t2和t3也开始请求锁,但是此时t1还没有释放锁,所以t2、t3处于等... 查看详情

linux线程同步必知,常用方法揭秘!(代码片段)

一、为什么要线程同步在Linux多线程编程中,线程同步是一个非常重要的问题。如果线程之间没有正确地同步,就会导致程序出现一些意外的问题,例如:竞态条件(RaceCondition):多个线程同时修改同一个共享变量,可能会导致... 查看详情

再探同步与互斥(代码片段)

文章目录线程锁种无锁编程乐观锁设计一个乐观锁悲观锁如何选择自旋锁互斥锁读写锁设计读写锁使用读写锁死锁pthread_mutex_timedlock死锁产生死锁的避免与解决的基本方法lock_guard&&unique_locklock_guardunique_lock条件变量条件变量... 查看详情

再探同步与互斥(代码片段)

文章目录线程锁种无锁编程乐观锁设计一个乐观锁悲观锁如何选择自旋锁互斥锁读写锁设计读写锁使用读写锁死锁pthread_mutex_timedlock死锁产生死锁的避免与解决的基本方法lock_guard&&unique_locklock_guardunique_lock条件变量条件变量... 查看详情

7.2.4-并发多线程互斥锁(代码片段)

一互斥锁进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,而共享带来的是竞争,竞争带来的结果就是错乱,如下frommultiprocessingimportProcess,Lockimporttimedeftask(name):print("%s1"%name)time... 查看详情

c++线程间的互斥和通信(代码片段)

...简单总结条件变量(conditon_variable)生产者消费者线程模型产生问题解决问题原子类型(atomic)简单使用改良车站卖票互斥锁(mutex)为了更好地理解,互斥锁, 查看详情

linux线程安全篇(代码片段)

文章目录0、概述1、线程不安全举例1.1前提知识铺垫1.2场景模拟1.3代码模拟2、互斥2.1什么是互斥2.2互斥锁的原理&&特性2.3互斥锁的计数器如何保证原子性2.4互斥锁的接口2.4.1初始化接口2.4.2加锁接口2.4.3解锁接口2.4.4销毁接口... 查看详情

线程锁(代码片段)

线程的互斥锁fromthreadingimportThread,Lock#创建一个互斥锁mutex=Lock()deftask1():#锁定mutex.acquire()foriinrange(100):print("===================")#打开mutex.release()deftask2():mutex.acquire()foriinrange(100):print("!! 查看详情