我是靠谱客的博主 要减肥苗条,最近开发中收集的这篇文章主要介绍Linux系统编程:多线程同步1. 信号量2. 互斥量3. 条件变量4. 读写锁5. C++线程编程,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章内容

  • 1. 信号量
  • 2. 互斥量
  • 3. 条件变量
  • 4. 读写锁
  • 5. C++线程编程

1. 信号量

为了使总进程和子线程两者之间可以有序的打印,对上一篇文章末尾的程序添加信号量
用同一个数p,主进程p从3开始递增5次,线程p从3开始递减10次

#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include <semaphore.h>
using namespace std;

sem_t sem;         // 全局变量

void* handle(void* p){
        int* pn = (int*)p;
        for(int i=0;i<10;++i){
                sleep(1);
                sem_wait(&sem);       // 上锁
                cout << pthread_self() << ":" << --*pn << endl;
                sem_post(&sem);       // 解锁
        }
        delete pn;
        return NULL;
}

pair<pthread_t,int*> test(){
        int* p = new int(3);
        pthread_t tid;
        pthread_create(&tid,NULL,handle,p);
        return {tid,p};
}

int main(){
        sem_init(&sem,0,1);           // 信号量创建
        cout << getpid() << endl;
        cout << pthread_self() << endl;

        auto [tid,p] = test();       // c++17   

        int n = 5;
        for(int i=0;i<5;++i){
                sleep(1);
                sem_wait(&sem);         // 上锁
                cout << pthread_self() << ":" << ++*p << endl;
                sem_post(&sem);         // 解锁
        }
        pthread_join(tid,NULL);
        sem_destroy(&sem);            // 信号量销毁
        return 0;
}

结果为:

[root@foundation1 C++7.13]# g++ thread4.cpp -pthread -std=c++17
[root@foundation1 C++7.13]# ./a.out
11460
139913218471744
139913200518912:2
139913218471744:3
139913200518912:2
139913218471744:3
139913200518912:2
139913218471744:3
139913200518912:2
139913218471744:3
139913200518912:2
139913218471744:3
139913200518912:2
139913200518912:1
139913200518912:0
139913200518912:-1
139913200518912:-2

并发过程中在2和3僵持,等待阶段开始递减

2. 互斥量

分类:

分类实现特点
静态分配互斥量pthread_mutex_t mutex= PTHREAD_MUTEX_INITIALIZER;简单
动态分配互斥量pthread_mutex_init(&mutex, NULL); pthread_mutex_destroy(&mutex);可以设置更多的选项

操作:

操作函数
加锁int pthread_mutex_lock(pthread_t *mutex)
尝试加锁int pthread_mutex_trylock(pthread_t *mutex)
解锁int pthread_mutex_unlock(pthread_t *mutex)

示例:
使用静态分配互斥量 pthread_mutex_t 互斥锁

加锁 pthread_mutex_lock(&互斥锁)

解锁 pthread_mutex_unlock(&互斥锁)

使用动态分配互斥量 pthread_mutex_init(&互斥锁, NULL);
动态分配销毁 pthread_mutex_destroy(&互斥锁);
(也可以不加)

互斥量,也叫互斥锁,比信号量简单一些
把之前的所换成互拆锁

#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include <semaphore.h>
using namespace std;

// sem_t sem;
pthread_mutex_t mutex; // = PTHREAD_MUTEX_INITIALIZER;

void* handle(void* p){
        int* pn = (int*)p;
        for(int i=0;i<10;++i){
                sleep(1);
                // sem_wait(&sem);  
                pthread_mutex_lock(&mutex);            // 上互斥锁
                cout << pthread_self() << ":" << --*pn << endl;
                pthread_mutex_unlock(&mutex);          // 解互斥锁
                //sem_post(&sem);     
        }
        delete pn;
        return NULL;
}

pair<pthread_t,int*> test(){
        int* p = new int(3);
        pthread_t tid;
        pthread_create(&tid,NULL,handle,p);
        return {tid,p};
}

int main(){
        pthread_mutex_init(&mutex,NULL);
        // sem_init(&sem,0,1);
        cout << getpid() << endl;
        cout << pthread_self() << endl;

        auto [tid,p] = test();        // c++17   

        int n = 0;
        // pthread_detach(tid);
        for(int i=0;i<5;++i){
                sleep(1);
                // sem_wait(&sem);
                pthread_mutex_lock(&mutex);             // 上互斥锁
                cout << pthread_self() << ":" << ++*p << endl;
                pthread_mutex_unlock(&mutex);           // 解互斥锁
                // sem_post(&sem);                    
        }
        pthread_join(tid,NULL);
        pthread_mutex_destroy(&mutex);
        return 0;
}

结果为:

[root@foundation1 C++7.13]# g++ thread5.cpp -pthread -std=c++17
[root@foundation1 C++7.13]# ./a.out
3817
140049311688512
140049293735680:2
140049311688512:3
140049293735680:2
140049311688512:3
140049293735680:2
140049311688512:3
140049293735680:2
140049311688512:3
140049293735680:2
140049311688512:3
140049293735680:2
140049293735680:1
140049293735680:0
140049293735680:-1
140049293735680:-2

信号量和互斥量的区别:

区别信号量互斥量
使用对象线程和进程线程
量值非负整数0或1
操作PV操作可由不同线程完成加锁和解锁必须由同一线程使用
应用用于线程的同步用于线程的互斥

互斥:主要关注于资源访问的唯一性和排他性。
同步:主要关注于操作的顺序,同步以互斥为前提。

3. 条件变量

条件变量: 线程挂起直到共享数据的某些条件得到满足(完成条件后再执行线程)

分类:

分类实现特点
静态分配条件变量pthread_cond_t cond = PTHREAD_COND_INITIALIZER;简单
动态分配条件变量pthread_cond_init(&cond, NULL);pthread_cond_destroy(&cond);可以设置更多的选项

操作:

操作函数
条件等待int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
计时等待int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
单个激活int pthread_cond_signal(pthread_cond_t *cond)
全部激活int pthread_cond_broadcast(pthread_cond_t *cond)

示例:

每到5秒计算一下和

#include <iostream>
#include <pthread.h>
#include <vector>
#include <numeric>
#include <unistd.h>     // sleep
using namespace std;

// 子线程
void* sum(void* data){
        vector<int>& p = *(vector<int>*)data;
        while(true){
                sleep(5);
                cout << "sum:" << accumulate(p.begin(),p.end(),0) << endl;      // p中所有数的和
        }
}

int main(){
        vector<int> data;

        pthread_t tid;
        pthread_create(&tid,NULL,sum,&data);        // 创建线程

        // 主线程
        int n;
        while(cin >> n){
                data.push_back(n);
        }

        pthread_join(tid,NULL);         // 合并线程
}

结果为:

[root@foundation1 C++7.13]# g++ cond.cpp -pthread
[root@foundation1 C++7.13]# ./a.out
sum:0
1
2
sum:3
sum:3
3
4
5
sum:15
sum:15
^C

等到输入五个后再求和,每次清零

静态分配条件变量 pthread_cond_t 条件变量 = PTHREAD_COND_INITIALIZER;

条件等待 pthread_cond_wait(&条件变量, &互斥量)
这里为什么要写互斥锁?
因为这条代码要控制这个互斥锁,要先解锁让别的线程使用,等满足条件后,会抢锁自己用

单个激活 pthread_cond_signal(&条件变量)

#include <iostream>
#include <pthread.h>
#include <vector>
#include <numeric>
#include <unistd.h>
using namespace std;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;     // 静态互斥量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;       // 静态条件变量

void* sum(void* data){
        vector<int>& p = *(vector<int>*)data;
        while(true){
                pthread_mutex_lock(&mutex);       // 互斥量上锁
                if(p.size()<5) pthread_cond_wait(&cond,&mutex);       // 子线程如果在这个条件下,等待
                cout << "sum:" << accumulate(p.begin(),p.end(),0) << endl;
                p.clear();
                pthread_mutex_unlock(&mutex);     // 互斥量解锁
        }
}

int main(){
        vector<int> data;
        pthread_t tid;
        pthread_create(&tid,NULL,sum,&data);

        int n;
        while(cin >> n){
                pthread_mutex_lock(&mutex);       // 互斥量上锁
                data.push_back(n);
                if(data.size()>=5) pthread_cond_signal(&cond);     // 主线程如果在这个条件下,发送
                pthread_mutex_unlock(&mutex);     // 互斥量解锁
        }

        pthread_join(tid,NULL);
}

结果为:

[root@foundation1 C++7.13]# g++ cond2.cpp -pthread
[root@foundation1 C++7.13]# ./a.out
1
2
3
4
5
sum:15
2
1
2
1
2
sum:8
^C

使用动态分配的方式

动态分配条件变量 pthread_cond_init(&条件变量, NULL);
动态分配销毁pthread_cond_destroy(&cond);

定义一个类,把变量汇总

#include <iostream>
#include <pthread.h>
#include <vector>
#include <numeric>
#include <unistd.h>
using namespace std;

struct Data{
        vector<int>& data;
        pthread_mutex_t& mutex;
        pthread_cond_t& cond;
};

void* sum(void* data){
        vector<int>& p = ((Data*)data)->data;
        pthread_mutex_t& mutex = ((Data*)data)->mutex;
        pthread_cond_t& cond = ((Data*)data)->cond;

        while(true){
                pthread_mutex_lock(&mutex);
                if(p.size()<5) pthread_cond_wait(&cond,&mutex);       // 子线程不满足条件,等
                cout << "sum:" << accumulate(p.begin(),p.end(),0) << endl;
                p.clear();
                pthread_mutex_unlock(&mutex);
        }
}

int main(){
        pthread_mutex_t mutex; // = PTHREAD_MUTEX_INITIALIZER;
        pthread_cond_t cond; //  = PTHREAD_COND_INITIALIZER;
        pthread_mutex_init(&mutex,NULL);
        pthread_cond_init(&cond,NULL);
        vector<int> data;
        pthread_t tid;
        Data d = {data,mutex,cond};
        pthread_create(&tid,NULL,sum,&d);

        int n;
        while(cin >> n){
                pthread_mutex_lock(&mutex);
                data.push_back(n);
                if(data.size()>=5) pthread_cond_signal(&cond);     // 主线程满足条件,发送
                pthread_mutex_unlock(&mutex);
        }

        pthread_join(tid,NULL);
        pthread_mutex_destroy(&mutex);
        pthread_cond_destroy(&cond);
}

结果是一样的

4. 读写锁

有时几个读取过程可以共同读,这样可以提高工作效率,读写锁可以分为读锁和写锁
读锁:读的过程中其他读也可以进行读操作
写锁:写的过程中不能进行其他操作

分类:

分类实现特点
静态分配读写锁pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER简单
动态分配读写锁pthread_rwlock_init(&rwlock, NULL);pthread_rwlock_destroy(&rwlock);可以设置更多的选项

操作:

操作函数
读取锁int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
写入锁int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
解锁int pthread_rwlock_unlock(pthread_rwlock_t *rwlock)

5. C++线程编程

之前都是属于Linux线程编程,我们使用C++线程编程,实现之前的操作,更加简单

#include <thread>
#include <iostream>
#include <mutex>
using namespace std;

int main(){
        mutex m;   // 定义互斥锁

        // 子线程
        thread t( [&m](){                  // 引进变量
                for(int i=0;i<5;++i){
                        this_thread::sleep_for(1s);       // 停1秒
                        m.lock();          // 加锁
                        cout << this_thread::get_id() << ":" << i << endl;
                        m.unlock();        // 解锁
                }
        } );

        // 主线程
        for(int i=0;i<5;++i){
                this_thread::sleep_for(1s);
                m.lock();                  // 加锁
                cout << this_thread::get_id() << ":" << i << endl;
                m.unlock();                // 解锁
        }

        t.join();      // 线程合并,等一下
}

结果为:

[root@foundation1 C++7.13]# g++ xian.cpp -pthread
[root@foundation1 C++7.13]# ./a.out
140127224375104:0
140127206422272:0
140127224375104:1
140127206422272:1
140127224375104:2
140127206422272:2
140127224375104:3
140127206422272:3
140127206422272:4
140127224375104:4

等到输入五个后再求和,每次清零
面对c++线程编程的条件变量 cond.wait 时,需要在前面定义唯一锁:unique_lock<mutex> lock(m);
对于条件变量 cond.notify_one 时可定义为 lock_guard<mutex> lock(m);
两者都有加锁和解锁的功能

#include <thread>
#include <iostream>
#include <mutex>
#include <numeric>
#include <vector>
#include <condition_variable>
using namespace std;

int main(){
        mutex m;
        condition_variable cond;

        vector<int> vec;

        // 子线程
        thread t( [&](){
                while(true){
                        unique_lock<mutex> lock(m);         // 定义唯一锁
                        // m.lock();      
                        if(vec.size() < 5) cond.wait(lock);        // 条件变量,等
                        cout << "sum:" << accumulate(vec.begin(),vec.end(),0) << endl;
                        vec.clear();
                        // m.unlock();     
                }
        } );

        // 主线程
        int n;
        while(cin >> n){
                lock_guard<mutex> lock(m);
                // m.lock();            
                vec.push_back(n);
                if(vec.size() >= 5) cond.notify_one();          // 条件变量,发
                // m.unlock();          
        }

        t.join();
}

最后

以上就是要减肥苗条为你收集整理的Linux系统编程:多线程同步1. 信号量2. 互斥量3. 条件变量4. 读写锁5. C++线程编程的全部内容,希望文章能够帮你解决Linux系统编程:多线程同步1. 信号量2. 互斥量3. 条件变量4. 读写锁5. C++线程编程所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(40)

评论列表共有 0 条评论

立即
投稿
返回
顶部