• C++多线程同步总结


    关于C++多线程,写得好的博客太多了,内容丰富,排版又好看,就是难找。

    整体看过以后,本人也总结一下,仅作为日后参照。

    这里先推荐看过的几篇博文链接,非常值得一看。

    https://blog.csdn.net/dingdingdodo/article/details/108477195

    https://www.cnblogs.com/yinbiao/p/11190336.html

    http://zhangxiaoya.github.io/2015/05/15/multi-thread-of-c-program-language-on-linux/

    https://www.cnblogs.com/hesper/p/10738987.html

    https://blog.csdn.net/qq_39382769/article/details/96075346

    注:本人所用IDE为Dev-C++。

    重在简洁啊,而且既能用windows平台下的,也能用linux平台下的多线程机制。

    一:C++11规范下的线程库

    1.C++11 线程库的基本用法:创建线程、分离线程

    #include<iostream>
    #include<thread>
    #include<windows.h>
    using namespace std;
    void threadProc()
    {
    	cout<<"this is in threadProc\n";
    	cout<<"thread1's id is "<<this_thread::get_id()<<endl; //获取所属线程的id 
    }
    void threadProc2(int num)
    {
    	cout<<"thread num = "<<num<<endl;
    }
    void threadProc3()
    {
    	cout<<"this thread is detached\n";
    }
    void threadProc4()
    {
    	cout<<"this thread is detached and won't print in the same console.'\n";
    }
    int main()
    {
    	thread a;//创建线程1,定义线程,后面再分配任务 
    	a = thread(threadProc);
    	thread b(threadProc2,5);//创建线程2 ,定义线程的时候分配任务,参数类似于printf一样,可以为多个 
    	a.join();
    	b.join();//采用join,主线程会阻塞等待子线程执行完毕 
    	thread c(threadProc3);
    	c.detach();//采用detach,主线程不会等,这个线程开启早,还能输出到主线程的控制台 
    	cout<<"main thread exit"<<endl;
    	thread d(threadProc4);
    	d.detach();//这个线程太晚了,主线程已经结束,不能输出到主线程的控制台了 
    }
    

      

    运行结果:

    2.基本的互斥锁

    上述运行,输出语句显然没有顺序执行,为了达到一行一行输出的效果,可以使用最基本的互斥锁。

    #include<iostream>
    #include<thread>
    #include<mutex>
    using namespace std;
    mutex mu;//互斥锁 
    void test1()
    {
        for(int i=0;i<5;i++)
        {
    //        mu.lock();//锁住 
            cout<<"test1 i = "<<i<<endl;
    //        mu.unlock();//释放 
        }
    }
    void test2()
    {
        for(int j=0;j<5;j++)
        {
    //        mu.lock();
            cout<<"test2 j = "<<j<<endl;
    //        mu.unlock();
        }
    }
    int main()
    {
        thread a(test1);
        thread b(test2);
        a.join();
        b.join();
        cout<<"main thread finish."<<endl;
    } 

    运行结果1:

     不加锁的话,输出就会混乱。

    这里打开4行注释,重新运行。

    运行结果2:

     可以简单理解为,test1获得锁以后,test2调用lock(),就会阻塞执行,直到test1()调用unlock()释放锁。

    3.lock_guard.

    #include<iostream>
    #include<thread>
    #include<mutex>
    using namespace std;
    mutex mu;//互斥锁 
    /*
    lock_guard<mutex> locka(mu);
    作用范围为从这一行开始,到那一次循环结束,还不用自己手动解锁。 
    */
    void test1()
    {
        for(int i=0;i<5;i++)
        {
            lock_guard<mutex> locka(mu); 
            cout<<"test1 i = "<<i<<endl;
        }
    }
    void test2()
    {
        for(int j=0;j<5;j++)
        {
            lock_guard<mutex> lock(mu);
            cout<<"test2 j = "<<j<<endl;
        }
    }
    int main()
    {
        thread a(test1);
        thread b(test2);
        a.join();
        b.join();
        cout<<"main thread finish."<<endl;
    } 

    运行结果:

    4.unique_lock

    #include<iostream>
    #include<thread>
    #include<mutex>
    using namespace std;
    mutex mu;//互斥锁 
    void test1()
    {
        for(int i=0;i<5;i++)
        {
            unique_lock<mutex> locka(mu,defer_lock); 
            cout<<"test1 i = "<<i<<endl;
            
            locka.lock();
            cout<<"this is lock1"<<endl;
        }
    }
    void test2()
    {
        for(int j=0;j<5;j++)
        {
            unique_lock<mutex> locka(mu); 
            cout<<"test2 j = "<<j<<endl;
            locka.unlock();
            locka.lock();
            cout<<"this is lock2"<<endl;
        }
    }
    int main()
    {
        thread a(test1);
        thread b(test2);
        a.join();
        b.join();
        cout<<"main thread finish."<<endl;
    } 

    运行结果:

     5.condition_variable

    #include<iostream>
    #include<thread>
    #include<mutex>
    #include<condition_variable>
    using namespace std;
    mutex mu;
    condition_variable cv;
    bool print = false;
    void test1()
    {
        for(int i=0;i<5;i++)
        {
            unique_lock<mutex> l(mu);
            cout<<"test1 i = "<<i<<endl;
            cv.notify_one();
            print = true;
        }
    }
    void test2()
    {
        for(int j=0;j<5;j++)
        {
            unique_lock<mutex> l(mu);
            if(!print)
            {
                cv.wait(l);
            }
            cout<<"test2 j = "<<j<<endl;
            print = false;
        }
    }
    int main()
    {
        thread a(test1);
        thread b(test2);
        a.join();
        b.join();
    }

    运行结果如下:

    二:W32API实现线程同步

    1.临界区

    #include<iostream>
    #include<thread>
    #include<windows.h>
    using namespace std;
    CRITICAL_SECTION section;//临界区变量
    
    void test1()
    {
        for(int i=0;i<5;i++)
        {
            EnterCriticalSection(&section);//类似于 mutex.lock() 
            cout<<"this is test1 i = "<<i<<endl;
         Sleep(1); LeaveCriticalSection(
    &section);//类似于 mutex.unlock() } } void test2() { for(int j=0;j<5;j++) { EnterCriticalSection(&section); cout<<"this is test2 j = "<<j<<endl;
         Sleep(1); LeaveCriticalSection(
    &section); } } int main() { InitializeCriticalSection(&section);//初始化临界区对象 thread a(test1); thread b(test2); a.join(); b.join(); DeleteCriticalSection(&section);//用完了,就删除临界区 }

    运行结果:

     效果类似于mutex,只是都要在执行完循环进行解锁的操作

    2.互斥锁。

    #include<iostream>
    #include<thread>
    #include<windows.h>
    using namespace std;
    HANDLE hmutex;
    void test1()
    {
        for(int i=0;i<5;i++)
        {
            WaitForSingleObject(hmutex,INFINITE);//类似于mutex.lock() 阻塞等待多少时间 
            cout<<"test1 i = "<<i<<endl;
            ReleaseMutex(hmutex);//类似于mutex.unlock() 释放互斥锁 
        }
    }
    void test2()
    {
        for(int j=0;j<5;j++)
        {
            WaitForSingleObject(hmutex,INFINITE);
            cout<<"test2 j = "<<j<<endl;
            ReleaseMutex(hmutex);
        }
    }
    int main()
    {
        hmutex = CreateMutex(NULL,FALSE,"mutex");//创建一个互斥锁 
        
        thread a(test1);
        thread b(test2);
        a.join();
        b.join();
        
        CloseHandle(hmutex);//释放句柄 
    }

    运行结果:

     效果基本差不多的,让输出有顺序是绰绰有余了。

    3.事件

    #include<iostream>
    #include<thread>
    #include<windows.h>
    using namespace std;
    HANDLE hevent;
    void test1()
    {
        for(int i=0;i<5;i++)
        {
            WaitForSingleObject(hevent,INFINITE);//类似于mutex.lock() 阻塞等待多少时间 
            cout<<"test1 i = "<<i<<endl;
            SetEvent(hevent);//类似于mutex.unlock() 释放互斥锁 
        }
    }
    void test2()
    {
        for(int j=0;j<5;j++)
        {
            WaitForSingleObject(hevent,INFINITE);
            cout<<"test2 j = "<<j<<endl;
            SetEvent(hevent);
        }
    }
    int main()
    {
        hevent = CreateEvent(NULL,FALSE,TRUE,"event");//创建一个事件 
        
        thread a(test1);
        thread b(test2);
        a.join();
        b.join();
        
        CloseHandle(hevent);//释放句柄 
    }

    运行结果:

    4.信号量

    #include<iostream>
    #include<thread>
    #include<windows.h>
    using namespace std;
    HANDLE sem;
    void test1()
    {
        for(int i=0;i<5;i++)
        {
            WaitForSingleObject(sem,INFINITE);//类似于mutex.lock() 阻塞等待多少时间 
            cout<<"test1 i = "<<i<<endl;
            ReleaseSemaphore(sem,1,NULL);//类似于mutex.unlock() 释放互斥锁 
        }
    }
    void test2()
    {
        for(int j=0;j<5;j++)
        {
            WaitForSingleObject(sem,INFINITE);
            cout<<"test2 j = "<<j<<endl;
            ReleaseSemaphore(sem,1,NULL);
        }
    }
    int main()
    {
        sem = CreateSemaphore(NULL,1,2,"semaphore");
        
        thread a(test1);
        thread b(test2);
        a.join();
        b.join();
        
        CloseHandle(sem);//释放句柄 
    }

    运行结果:

    三:linux支持的多线程同步

    1.互斥锁

    #include<iostream>
    #include<thread>
    #include<pthread.h>
    using namespace std;
    
    pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER;
    
    void test1()
    {
        for(int i=0;i<5;i++)
        {
            pthread_mutex_lock(&mu);//类似于mutex.lock() 阻塞等待多少时间 
            cout<<"test1 i = "<<i<<endl;
            pthread_mutex_unlock(&mu);//类似于mutex.unlock() 释放互斥锁 
        }
    }
    void test2()
    {
        for(int j=0;j<5;j++)
        {
            pthread_mutex_lock(&mu);
            cout<<"test2 j = "<<j<<endl;
            pthread_mutex_unlock(&mu);
        }
    }
    int main()
    {
        thread a(test1);
        thread b(test2);
        a.join();
        b.join();    
    }

    2.条件变量

    #include<iostream>
    #include<thread>
    #include<pthread.h>
    using namespace std;
    
    pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER;
    
    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    
    bool one = true;
    void test1()
    {
        pthread_mutex_lock(&mu);
        cout<<"test1 begin()"<<endl;
        while(one)
        {
            pthread_cond_wait(&cond,&mu);
        }
        cout<<"test1 continue"<<endl;
        pthread_mutex_unlock(&mu);
    }
    void test2()
    {
        pthread_mutex_lock(&mu);
        cout<<"test2 begin()"<<endl;
        
        one = false;
        pthread_mutex_unlock(&mu);
        cout<<"test2 finish"<<endl;
        pthread_cond_signal(&cond);
    }
    int main()
    {
        thread a(test1);
        thread b(test2);
        a.join();
        b.join();    
    }

    运行结果:

    3.信号量

    #include<iostream>
    #include<pthread.h>
    #include<semaphore.h>
    #include<thread>
    using namespace std;
    
    sem_t se;
    void test1()
    {
        for(int i=0;i<5;i++)
        {
            sem_wait(&se);//类似于mutex.lock() 阻塞等待多少时间 
            cout<<"test1 i = "<<i<<endl;
            sem_post(&se);//类似于mutex.unlock() 释放互斥锁 
        }
    }
    void test2()
    {
        for(int j=0;j<5;j++)
        {
            sem_wait(&se);;
            cout<<"test2 j = "<<j<<endl;
            sem_post(&se);
        }
    }
    
    int main()
    {
        sem_init(&se,0,1);//初始化信号量 
        thread a(test1);
        thread b(test2);
        a.join();
        b.join();
        sem_destroy(&se);//删除信号量 
    }

    4.读写锁

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <string.h>
    #include <pthread.h>
    
    int number = 0;
    
    // 读写锁
    pthread_rwlock_t lock;
    
    void *write_func(void *arg) {
        while (1) {
            pthread_rwlock_wrlock(&lock);
            number++;
            printf("+++++write: %lu, %d\n", pthread_self(),  number);
            pthread_rwlock_unlock(&lock);
            sleep(1);
        }
        return NULL;
    }
    
    void *read_func(void *arg) {
        while (1) {
            pthread_rwlock_rdlock(&lock);
            printf("======read: %lu, %d\n", pthread_self(), number);
            pthread_rwlock_unlock(&lock);
            sleep(1);
        }
        return NULL;
    }
    
    int main() {
        int i;
        pthread_t p[8];
    
        // 初始化读写锁
        pthread_rwlock_init(&lock, NULL);
    
        // 3个写线程
        for (i = 0; i < 3; i++) {
            pthread_create(&p[i], NULL, write_func, NULL);
        }
        
        // 5个读线程
        for (i = 3; i < 8; i++) {
            pthread_create(&p[i], NULL, read_func, NULL);
        }
    
        // 回收子线程
        for (i = 0; i < 8; i++) {
            pthread_join(p[i], NULL);
        }
    
        pthread_rwlock_destroy(&lock);
    
        return 0;
    }

    这一篇直接使用别人的代码了,麻烦,直接作为参考就好了。

    5.不使用C++11线程库创建线程

    #include<iostream>
    #include<pthread.h>
    using namespace std;
    void* test1(void*)
    {
        cout<<"hello world"<<endl;
    }
    
    int main()
    {
        pthread_t t1;
        pthread_create(&t1,NULL,test1,NULL);
        
        pthread_join(t1,NULL);
    }

    感觉挺麻烦,都不想多写了。

  • 相关阅读:
    配置Xmanager远程登录
    如何为ubuntu等Linux系统扩容(LVM)
    CentOS7配置iptables防火墙
    Cetnos搭建vsftp服务器
    vim设置
    zabbix 问题汇总
    转:常用验证正则表达式
    C#对象序列化成XML,以及自定义标签名
    改变FileUpload文件上传控件的显示方式,确认后上传
    改变FileUpload文件上传控件的显示方式,选择文件后自动上传
  • 原文地址:https://www.cnblogs.com/dayq/p/15970292.html
Copyright © 2020-2023  润新知