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

线程同步_02

写作时间:2026-07-25 02:23:02

POSIX信号量

初始化信号量

include

int sem_init(sem_t *sem, int pshared, unsigned int value);

参数:

pshared: 0 表⽰线程间共享,⾮零表⽰进程间共享

value :信号量初始值

‍

销毁信号量

int sem_destroy(sem_t *sem);

‍

等待信号量

作用:等待信号量,并将信号量的值减 1

int sem_wait(sem_t *sem);

‍

发布信号量

功能:发布信号量,表⽰资源使⽤完毕,可以归还资源了,并将信号量值加 1 。

int sem_post(sem_t *sem);

‍

基于环形队列的⽣产消费模型

Mutex.hpp

#pragma once

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

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

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

    pthread_mutex_t *Ptr()
    {
        return &_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;
};

‍

Sem.hpp

#ifndef __SEM_HPP
#define __SEM_HPP

#include<iostream>
#include<semaphore.h>

class Sem
{
public:
    Sem(int init_val)
    {
        if(init_val > 0)
        {
            int n = sem_init(&_sem , 0 , init_val);
            (void)n;
        }
    }

    void P()
    {
        int n = sem_wait(&_sem);
        (void)n;
    }

    void V()
    {
        int n = sem_post(&_sem);
        (void)n;
    }

    ~Sem()
    {
        int n = sem_destroy(&_sem);
        (void)n;
    }
private:
    sem_t _sem;
};

#endif

‍

RingQueue.hpp

#pragma once

#include<iostream>
#include<string>
#include<pthread.h>
#include<vector>
#include"Sem.hpp"
#include"Mutex.hpp"


const int defaultcap = 5;

template<typename T>
class RingQueue
{
public:
    RingQueue(int cap = defaultcap):
    _cap(cap),
    _rq(cap),
    _consumer_step(0),
    _productor_step(0),
    _blank_sem(cap),
    _data_sem(0)
    {}

    void Enqueue(T &in)
    {
        // 1. 预定资源
        _blank_sem.P();

        {
            LockGuard lockguard(_pmutex);
            // 2. 定位生成位置
            _rq[_productor_step++] = in;
            _productor_step %= _cap;

        }

        // 3. 释放数据资源
        _data_sem.V();    
    }

    void Pop(T *out)
    {
        _data_sem.P();

        {
            LockGuard lockguard(_cmutex);
            *out = _rq[_consumer_step++];
            _consumer_step %= _cap;
        }

        _blank_sem.V();
    }

    ~RingQueue()
    {

    }
private:
    int _cap; // 环形队列容量
    std::vector<T> _rq;

    int _consumer_step; //消费位置
    int _productor_step; //生产位置

    Sem _blank_sem; // 格子资源计数器
    Sem _data_sem; //数据信号量

    Mutex _cmutex;
    Mutex _pmutex;

};

Task.hpp

#ifndef __TASK_HPP
#define __TASK_HPP

#include<iostream>
#include<string>
#include<functional>


// using task_t = std::function<void()>;

// void Print()
// {
//     std::cout<<"待处理任务" <<std::endl;
// }

class Task
{
public:
    Task(){}

    Task(int x , int y):_x(x) , _y(y)
    {}

    void Execute()
    {
        _result = _x + _y;
    }

    void operator()()
    {
        Execute();
    }

    std::string getResult()
    {
        return std::to_string(_x) + " + " + std::to_string(_y) + " = " +std::to_string(_result);         
    }

    std::string Question()
    {
        return std::to_string(_x) + " + " + std::to_string(_y) + " =?";
    }

    ~Task()
    {}

private:
    int _x;
    int _y;
    int _result;
};





#endif

‍

Main.cc

#include"RingQueue.hpp"
#include"Task.hpp"
#include <unistd.h>
#include<ctime>
#include<stdlib.h>

// Mutex cnt_lock;
// Mutex screen_lock;

// int data = 1;

// int GetData()
// {
//     cnt_lock.Lock();
//     int result = data++;
//     cnt_lock.Unlock();
//     return result;
// }

// void Print(const std::string name , const std::string &info)
// {
//     screen_lock.Lock();
//     std::cout<<name <<" : " <<info <<std::endl;
//     screen_lock.Unlock();
// }

// class ThreadData
// {
// public:
//     ThreadData(RingQueue<int> *r , const std::string &n):rq(r) , name(n)
//     {
// 
//     }
// 
//     ~ThreadData()
//     {
// 
//     }
// public:
//     std::string name;
//     RingQueue<int> *rq;
// };


void *ProductorRoutine(void *args)
{
    RingQueue<Task> *rq = static_cast<RingQueue<Task> *>(args);

    while(true)
    {
        int x = rand() % 9 + 1;
        usleep(1000);
        int y = rand() % 9 + 1;
        Task t(x , y);

        rq->Enqueue(t);
        std::cout<<"生产任务" <<t.Question() <<std::endl;
    }

    // ThreadData *td = static_cast<ThreadData*>(args);
    // pthread_setname_np(pthread_self() , td->name.c_str());
    // while(true)
    // {
    //     int data = GetData();
    //     sleep(1);
    //     td->rq->Enqueue(data);
    //     Print(td->name , " 生产数据 " + std::to_string(data));
    // }
}

void *ConsumerRoutine(void* args)
{
    RingQueue<Task> *rq = static_cast<RingQueue<Task> *>(args);

    int data = 0;

    while(true)
    {
        sleep(1);

        Task t;
        rq->Pop(&t);

        t();
        std::cout<<"消费完成任务 " <<t.getResult() <<std::endl;
    }

    // ThreadData *td = static_cast<ThreadData*>(args);
    // pthread_setname_np(pthread_self() , td->name.c_str());
    // 
    // int data = 0;
    // while(true)
    // {
    //     // sleep(1);
    //     td->rq->Pop(&data);
    //     Print(td->name , " 消费数据 " + std::to_string(data));
    // }
}

int main()
{
    srand(time(nullptr) ^ getpid());

    RingQueue<int> *rq = new RingQueue<int>();
    pthread_t c , p;
    pthread_create(&p , nullptr , ProductorRoutine , rq);
    pthread_create(&c , nullptr , ConsumerRoutine , rq);


    pthread_join(c , nullptr);
    pthread_join(p , nullptr);

    // ThreadData *td0 = new ThreadData(rq , "product-1");
    // pthread_create(p , nullptr , ProductorRoutine , td0);
    // ThreadData *td1 = new ThreadData(rq , "product-2");
    // pthread_create(p+1 , nullptr , ProductorRoutine , td1);
    // ThreadData *td2 = new ThreadData(rq , "product-3");
    // pthread_create(p+2 , nullptr , ProductorRoutine , td2);

    // ThreadData *td3 = new ThreadData(rq , "consumer-1");
    // pthread_create(c , nullptr , ConsumerRoutine , td3);
    // ThreadData *td4 = new ThreadData(rq , "consumer-2");
    // pthread_create(c+1 , nullptr , ConsumerRoutine , td4);



    // pthread_join(c[0] , nullptr);
    // pthread_join(c[1] , nullptr);
    // pthread_join(p[0] , nullptr);
    // pthread_join(p[1] , nullptr);
    // pthread_join(p[2] , nullptr);

    return 0;
}

‍

makefile

cp_ring:Main.cc
    g++ -o $@ $^ -std=c++14
.PHONY:clean
clean:
    rm -f cp_ring

‍

avatar

胧

RECOMMENDED

线程控制

2026-07-21 01:47:21

线程池——单例模式

2026-07-27 22:36:45

进程控制

2026-07-11 20:27:31

Table of Contents