Linux高级编程——多线程控制(互斥锁、信号量)

多线程同步控制

常用的同步控制方法:

  • 互斥锁(Mutex)
  • 信号量(Semaphore)
  • 条件变量(Condition Variable)
  • 读写锁(Read-Write Lock)
  • 自旋锁(Spin Lock)
互斥锁(Mutex)

多个线程对某个只能独占使用的资源进行互斥访问可以使用互斥锁。

当某个线程调用 pthread_mutex_lock 函数时:

  • 如果互斥锁已经处于锁定状态,该函数会阻塞调用线程的执行,直到其他线程解锁才可能从 pthread_mutex_lock 函数返回继续往下执行。
  • 如果互斥锁处于未锁定状态,那么 pthread_mutex_lock 函数就加锁成功并立即返回,其他晚一步调用 pthread_mutex_lock 函数的所有线程都会陷入阻塞状态。
  • 加锁成功的线程执行完需要保护的代码之后一旦解锁,那些处于阻塞状态的线程又会有一个线程取消阻塞继续往下执行(pthread_mutex_lock 函数返回了)。
    头文件#include <pthread.h>
信号量(Semaphore)

一个特殊的全局变量,用于控制同时访问特定资源的线程数量,支持 P/V 操作,并且它们都是原子性操作。

信号量的值就表示当前可用资源的数量。

P 操作:即等待信号,调用 sem_wait 实现;

  • 如果信号量的当前值大于 0,P 操作会将其 - 1并立即返回。

  • 如果信号量的当前值等于 0,P操作将会阻塞当前线程,直到信号量的值大于 0 或被信号打断。

V 操作:即发送信号,调用 sem_post 实现;直接将当前信号量的当前值+ 1 并返回。

头文件#include <semaphore.h>

//多个线程同时使用,实现互斥

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

#define N 10

//volatile int use_flag = 1;
//pthread_mutex_t m = PTHREAD_COND_INITIALIZER;

sem_t s;

void* thr_fun(void* arg);


int main()
{
    int i;
    pthread_t tids[N];

    srand(time(NULL));
        
    //pthread_mutex_init(&m, NULL);
    sem_init(&s, 0, 1);// 3为信号量的值,表可用资源的数量 // 0表不同进程线程空间不可共享,共享为1(多个进程的不同线程共抢一个厕所)


    for(i = 0; i < N; i++)
    {
        if(pthread_create(&tids[i], NULL, thr_fun, (void*)(long)i))
        {
            perror("pthread_create");
        }
    }

    for(i = 0; i < N; i++)
    {
        pthread_join(tids[i], NULL);
    }

    //pthread_mutex_destroy(&m);  //销毁互斥锁
    sem_destroy(&s);

    return 0;
}


void* thr_fun(void* arg)
{
    int i = (int)(long)arg;
    
    //下面两条语句并非原子性操作,所以不太安全,有可能某个线程执行到一半的时候被打断。
    //while (!use_flag);
    //use_flag--;
    
    //pthread_mutex_lock(&m);     // 加锁,原子性操作
    /*if(i == 5)    
    {
        while(pthread_mutex_trylock(&m))  //尝试加锁,失败,不阻塞,立即返回
        {
            printf("我正在处理其他事情...\n");
            sleep(1);        
        }
    }
    else pthread_mutex_lock(&m);
    */
    // P 操作
    sem_wait(&s);

    printf("%d号进入厕所...\n", i);
    sleep(rand() % 5 + 1);      // 1s ~ 5s
    printf("%d号离开厕所!\n", i);
    
    //下面两条语句并非原子性操作,所以不太安全,有可能某个线程执行到一半的时候被打断。
    //use_flag++;
    
    //pthread_mutex_unlock(&m);   //

    // V 操作
    sem_post(&s);

    pthread_exit(NULL);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值