胧の宝藏之地
首页项目归档照片墙音乐灵境说说杂谈友链关于
封面

线程互斥

写作时间:2026-07-23 23:19:41

相关概念

共享资源

临界资源:多线程执⾏流被保护的共享的资源就叫做临界资源

临界区:每个线程内部,访问临界资源的 代码,就叫做临界区

互斥:任何时刻,互斥保证有且只有⼀个执⾏流进⼊临界区,访问临界资源,通常对临界资源起 保护作⽤

原⼦性:不会被任何调度机制打断的操作,该操作只有两态,要么完成, 要么未完成

‍

互斥量mutex

引入原因

⼤部分情况,线程使⽤的数据都是局部变量,变量的地址空间在线程栈空间内,这种情况,变量归属单个线程,其他线程⽆法获得这种变量。

但有时候,很多变量都需要在线程间共享,这样的变量称为共享变量,可以通过数据的共享,完 成线程之间的交互。

多个线程并发的操作共享变量,会带来⼀些问题。

‍

样例代码

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

int ticket = 100;

void *route(void *arg)
{
    char *id = (char *)arg;
    while (1)
    {
        if (ticket > 0)
        {
            usleep(1000);
            printf("%s sells ticket:%d\n", id, ticket);
            ticket--;
        }
        else
        {
            break;
        }
    }
}

int main(void)
{
    pthread_t t1, t2, t3, t4;
    pthread_create(&t1, NULL, route, (void *)"thread 1");
    pthread_create(&t2, NULL, route, (void *)"thread 2");
    pthread_create(&t3, NULL, route, (void *)"thread 3");
    pthread_create(&t4, NULL, route, (void *)"thread 4");
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    pthread_join(t3, NULL);
    pthread_join(t4, NULL);

    return 0;
}

互斥量的接⼝

初始化

静态分配

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER

‍

动态分配

int pthread_mutex_init(pthread_mutex_t restrict mutex, const pthread_mutexattr_t restrict attr);

参数:

mutex :要初始化的互斥量

attr : NULL

销毁:

int pthread_mutex_destroy(pthread_mutex_t *mutex) ;

1、静态分配的互斥量不需要销毁

2、不要销毁⼀个已经加锁的互斥量

3、已经销毁的互斥量,要确保后⾯不会有线程再尝试加锁

‍

互斥量加锁和解锁

int pthread_mutex_lock(pthread_mutex_t mutex); // 加锁

int pthread_mutex_unlock(pthread_mutex_t mutex); // 解锁

返回值 : 成功返回 0, 失败返回错误号

‍

封装互斥量

Mutex.hpp

#pragma once

#include<iostream>
#include<pthread.h>

class Mutex
{
public:
    Mutex()
    {
        pthread_mutex_init(&_lock , nullptr);
    }

    void Lock()
    {
        pthread_mutex_lock(&_lock);
    }

    void Unlock()
    {
        pthread_mutex_unlock(&_lock);
    }

    ~Mutex()
    {
        pthread_mutex_destroy(&_lock);
    }
private:
    pthread_mutex_t _lock;
};

class LockGuard
{
public:
    LockGuard(Mutex &lock):_lockref(lock)
    {
        _lockref.Lock();
    }

    ~LockGuard()
    {
        _lockref.Unlock();
    }
private:
    Mutex &_lockref;
};

Main.cc

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sched.h>
#include "Mutex.hpp"

int ticket = 1000;
Mutex lock;

void *route(void *arg)
{
    char *id = (char *)arg;
    while (1)
    {
        {
        // 在该作用域中创建lockguard类对象时自动调用构造函数,此时成员Mutex类(_Mutex)会通过构造函数初始化互斥量,并对互斥量上锁
            LockGuard lockguard(lock);
            if (ticket > 0)
            {
                usleep(1000);
                printf("%s sells ticket:%d\n", id, ticket);
                ticket--;
            }
            else
            {
                break;
            }
        // 离开该作用域时lockguard 会自动调用析构函数对互斥量进行解锁操作
        }
    }
    return nullptr;
}

int main(void)
{
    pthread_t t1, t2, t3, t4;

    pthread_create(&t1, NULL, route, (void *)"thread-1");
    pthread_create(&t2, NULL, route, (void *)"thread-2");
    pthread_create(&t3, NULL, route, (void *)"thread-3");
    pthread_create(&t4, NULL, route, (void *)"thread-4");

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    pthread_join(t3, NULL);
    pthread_join(t4, NULL);

    return 0;
}

makefile

thread:Main.cc
    g++ -o $@ $^ -std=c++11

.PHONY:clean
clean:
    rm -f thread

‍

avatar

胧

RECOMMENDED

线程控制

2026-07-21 01:47:21

线程池——单例模式

2026-07-27 22:36:45

进程控制

2026-07-11 20:27:31

Table of Contents