Linux 下信号量与锁的配合使用学习

  还是很早之前看的《Unix环境高级编程》,今天重新学习线程,又看了一下,感觉理解又加深了,记录一下以前不理解的地方。

例子
pthread_mutex_t  lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  full = PTHREAD_COND_INITIALIZER;
pthread_cond_t  empty1 = PTHREAD_COND_INITIALIZER;
std::vector v = {};
int cap = 3;
void *producer(void *args)
{
    for(auto i = 0 ; i <30 ;++i)
    {
        pthread_mutex_lock(&lock);
        printf("生产者开始生产\n");
        v.push_back(1);
        if(v.size() >= cap)
        {
            printf("发送 full 信号!");
            pthread_cond_signal(&full);
            pthread_mutex_unlock(&lock);
            pthread_cond_wait(&empty1,&lock);
        }
        pthread_mutex_unlock(&lock);
    }
    return nullptr;
}
void *consume(void *args)
{
    for(auto i = 0 ; i <30 ;++i)
    {
        pthread_mutex_lock(&lock);
        while(v.empty())
        {
            pthread_cond_wait(&full,&lock);
        }
        printf("消耗者开始消耗\n");
        v.clear();
        pthread_cond_signal(&empty1);
        printf("发送消费完毕信号!\n");
        pthread_mutex_unlock(&lock);
    }
}
int main()
{
    pthread_t t1; pthread_t t2;
    pthread_create(&t1,nullptr,consume,nullptr);
    usleep(100);
    pthread_create(&t2,nullptr,producer,nullptr);
    pthread_join(t1,nullptr);
    pthread_join(t2,nullptr);
    std::cout<<"全部结束!"<
结果
生产者开始生产生产者开始生产生产者开始生产发送 full 信号!
消耗者开始消耗
发送消费完毕信号!
生产者开始生产生产者开始生产生产者开始生产发送 full 信号!
消耗者开始消耗
发送消费完毕信号!
生产者开始生产生产者开始生产生产者开始生产发送 full 信号!
消耗者开始消耗
发送消费完毕信号!
生产者开始生产生产者开始生产生产者开始生产发送 full 信号!
消耗者开始消耗
发送消费完毕信号!
生产者开始生产生产者开始生产生产者开始生产发送 full 信号!
消耗者开始消耗
发送消费完毕信号!
生产者开始生产生产者开始生产生产者开始生产发送 full 信号!
消耗者开始消耗
发送消费完毕信号!
生产者开始生产生产者开始生产生产者开始生产发送 full 信号!
消耗者开始消耗
发送消费完毕信号!
生产者开始生产生产者开始生产生产者开始生产发送 full 信号!
消耗者开始消耗
发送消费完毕信号!
生产者开始生产生产者开始生产生产者开始生产发送 full 信号!
消耗者开始消耗
发送消费完毕信号!
生产者开始生产生产者开始生产生产者开始生产发送 full 信号!
消耗者开始消耗
发送消费完毕信号!

pthread

基本接口
//返回当前线程id
pthread_t pthread_self(void);

//判断两个线程是否相等
int pthread_equal(pthread_t t1, pthread_t t2);

//pthread_exit()线程退出,能指定返回值,其他线程通过pthread_join()函数获取该线程的返回值 
void pthread_exit(void *res); 

//停止相应的线程,成功返回0
int pthread_cancel(pthread_t t);

//向某个线程发送某个信号
int pthread_kill(pthread_t t, int sig);

//创建线程
int pthread_create(pthread_t *th, const pthread_attr_t *attr, void *(* func)(void *), void *arg);

//等待一个线程的结束,线程间同步的操作,res来自于pthread_exit设置的值
int pthread_join(pthread_t t, void **res);

//分离线程 t线程就编程unjoinable的了
int pthread_detach(pthread_t t);

mutex

基本接口
int pthread_mutex_lock(pthread_mutex_t *m);//上锁

int pthread_mutex_unlock(pthread_mutex_t *m);//解锁

int pthread_mutex_trylock(pthread_mutex_t *m);//尝试上锁试图获取一个互斥变量

int pthread_mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *a);//初始化锁

int pthread_mutex_destroy(pthread_mutex_t *m);//析构锁

cond

基本接口
//初始化条件变量
int pthread_cond_init(pthread_cond_t *cv, const pthread_condattr_t *a);

//析构条件变量
int pthread_cond_destroy(pthread_cond_t *cv);

//发送一个信号给另外一个正在处于阻塞等待状态的线程,使其脱离阻塞状态
int pthread_cond_signal (pthread_cond_t *cv);

//发送一个信号给所有正在处于阻塞等待状态的线程,使其脱离阻塞状态
int pthread_cond_broadcast (pthread_cond_t *cv);

//一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)
int pthread_cond_wait (pthread_cond_t *cv, pthread_mutex_t *external_mutex);
pthread_cond_signal

  pthread_cond_signal 通过条件变量cond发送消息,若多个消息在等待,它只唤醒一个。

pthread_cond_wait

  对于接口 pthread_cond_wait,总和一个互斥锁结合使用。在调用pthread_cond_wait前要先获取锁。pthread_cond_wait函数执行时先自动释放指定的锁,然后等待条件变量的变化。在函数调用返回之前,自动将指定的互斥量重新锁住,这一步是原子操作!因为这步会重新获得锁,所以我们在调用pthread_cond_signal或者pthread_cond_broadcast之后必须释放锁!否则pthread_cond_wait的线程会继续阻塞。

实现一个线程类

class Mutex{
public:
    explicit Mutex():mutex(PTHREAD_MUTEX_INITIALIZER){
    }
    void lock()
    {
        pthread_mutex_lock(&mutex);
    }
    void unlock()
    {
        pthread_mutex_unlock(&mutex);
    }
    ~Mutex()
    {
        pthread_mutex_destroy(&mutex);
    }
    pthread_mutex_t  mutex;
};

class Cond{
public:
    Cond():cond(PTHREAD_COND_INITIALIZER)
    {

    }
    void signal()
    {
        pthread_cond_signal(&cond);
    }
    void broadcast()
    {
        pthread_cond_broadcast(&cond);
    }
    void wait(Mutex &mutex)
    {
        pthread_cond_wait(&cond,(&mutex.mutex));
    }
    ~Cond()
    {
        pthread_cond_destroy(&cond);
    }
private:
    pthread_cond_t cond;
};

class Thread{
public:
    explicit Thread(std::string name = "Thread") : name(std::move(name)),
                                                   alive(false),joinable(false),thread(0) {}
    bool Start()
    {
        if(alive)
        {
            printf("进程正在运行");
            return true;
        }
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        if(!joinable)
            pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
        if(0 != pthread_create(&thread,nullptr,Thread::threadFuc,this))
        {
            cout<<"创建线程失败"<mutex.lock();
        thread->alive = true;
        thread->cond.signal();
        thread->mutex.unlock();
        thread->Run();
        return nullptr;
    }
    virtual void Run()
    {
        //业务逻辑
        ofstream out("out.txt");
        int i = 12;
        while(i > 0)
        {
            i--;
            if (out.is_open())
            {
                out << "This is a line.\n";
            }
        }
        out.close();
    }
private:
    std::string name;
    bool alive;
    bool joinable;//是否可以等待线程结束的
    Cond cond;
    Mutex mutex;
    pthread_t thread{};
};
int main()
{
    auto thread = new Thread("业务1");
    thread->Start();
    pthread_canel();//如果不调用这个的话 那么主线程退出,整个程序都会结束,detach出来的线程也就挂了。
    std::cout<<"全部结束!"<

你可能感兴趣的:(Linux 下信号量与锁的配合使用学习)