C++多线程同步总结

关于C++多线程同步

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

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

#include
#include
#include
using namespace std;
void threadProc()
{
    cout<<"this is in threadProc
";
    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
";
}
void threadProc4()
{
    cout<<"this thread is detached and won't print in the same console.'
";
}
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();//
}

运行结果:

C++多线程同步总结插图

2、基本的互斥锁

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

#include
#include
#include
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;
} 

运行结果:

C++多线程同步总结插图(1)

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

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

运行结果:

C++多线程同步总结插图(2)

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

3、lock_guard

#include 
#include 
#include 

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

运行结果:

C++多线程同步总结插图(3)

4、unique_lock

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

运行结果:

C++多线程同步总结插图(4)

 5、condition_variable

#include
#include
#include
#include

using namespace std;

mutex mu;
condition_variable cv;
bool print = false;
void test7()
{
    for(int i=0;i<5;i++)
    {
        unique_lock l(mu);
        cout<<"test7 i = "<<i<<endl;
        cv.notify_one();
        print = true;
    }
}
void test8()
{
    for(int j=0;j<5;j++)
    {
        unique_lock l(mu);
        if(!print)
        {
            cv.wait(l);
        }
        cout<<"test8 j = "<<j<<endl;
        print = false;
    }
}
int main()
{
    thread a(test7);
    thread b(test8);
    a.join();
    b.join();
}

运行结果:

C++多线程同步总结插图(5)

二、Win32 API 实现线程同步

1、临界区

#include 
#include 
#include 

using namespace std;

CRITICAL_SECTION section;//临界区变量

void test01()
{
    for(int i=0;i<5;i++)
    {
        EnterCriticalSection(&section);//类似于 mutex.lock() 
        cout<<"this is test01 i = "<<i<<endl;
     Sleep(1);
        LeaveCriticalSection(&section);//类似于 mutex.unlock() 
    }
} 
void test02()
{
    for(int j=0;j<5;j++)
    {
        EnterCriticalSection(&section);
        cout<<"this is test02 j = "<<j<<endl;
     Sleep(1);
        LeaveCriticalSection(&section);
    }
}
int main()
{
    InitializeCriticalSection(&section);//初始化临界区对象
    
    thread a(test01);
    thread b(test02);
    a.join();
    b.join();
    DeleteCriticalSection(&section);//用完了,就删除临界区 
}

运行结果:

C++多线程同步总结插图(6)

C++多线程同步总结插图(7)

C++多线程同步总结插图(8)

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

2、互斥锁

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

运行结果:

C++多线程同步总结插图(9)

3、事件

#include
#include
#include

using namespace std;

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

运行结果:

C++多线程同步总结插图(10)

4、信号量

#include 
#include 
#include 

using namespace std;

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

运行结果:

C++多线程同步总结插图(11)

#include 
#include 
#include 
#include 
#include 
//#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define NAME_LINE   40
void* g_hMutex2 = NULL; //使用适当的初始化方式
//定义线程函数传入参数的结构体
typedef struct __TICKET
{
int nCount;
char strTicketName[NAME_LINE];
__TICKET() : nCount(0)
{
memset(strTicketName, 0, NAME_LINE * sizeof(char));
}
}TICKET;
typedef struct __THD_DATA
{
TICKET* pTicket;
char strThreadName[NAME_LINE];
__THD_DATA() : pTicket(NULL)
{
memset(strThreadName, 0, NAME_LINE * sizeof(char));
}
}THD_DATA;
//基本类型数据转换成字符串
template
std::string convertToString(const T val)
{
std::string s;
std::strstream ss;
ss <> s;
return s;
}
//售票程序
DWORD WINAPI SaleTicket(LPVOID lpParameter);
//售票系统
void Test2();
// 一个mutex变量控制同一个资源,因此会先打印完*再打印$
// 两个mutex变量则可能出现交替打印,因为不是修改统一资源
std::mutex mtx;  // mutex for critical section
void print_block(int n, char c)
{
mtx.lock();
for (int i = 0; i<n; i++)
{
std::cout << c;
}
std::cout << '
';
mtx.unlock();
}
void thread_1()
{
std::cout << "子线程1" << std::endl;
}
void thread_2(int x)
{
std::cout << "x:" << x << std::endl;
std::cout << "子线程2" << std::endl;
}
int f_multi_thread()
{
std::thread first(thread_1); // 开启线程,调用:thread_1()
std::thread second(thread_2, 100); // 开启线程,调用:thread_2(100)
//std::thread third(thread_2,3);//开启第3个线程,共享thread_2函数。
std::cout << "主线程
";
first.join(); //join()等待线程结束并清理资源(会阻塞)        
second.join();
std::cout << "子线程结束.
";//必须join完成
//std::thread th1(print_block, 50, '*');//线程1:打印*
//std::thread th2(print_block, 50, '$');//线程2:打印$
//th1.join();
//th2.join();
return 0;
}
void threadProc()
{
std::cout << "this is in threadProc
";
std::cout << "thread1's id is " << std::this_thread::get_id() << std::endl; //获取所属线程的id
}
void threadProc2(int num)
{
std::cout << "thread num = " << num << std::endl;
}
void threadProc3()
{
std::cout << "this thread is detached
";
}
void threadProc4()
{
std::cout << "this thread is detached and won't print in the same console.'
";
}
std::mutex mu;//互斥锁 
void test1()
{
for (int i = 0; i < 5; i++)
{
mu.lock();//锁住 
std::cout << "test1 i = " << i << std::endl;
mu.unlock();//释放 
}
}
void test2()
{
for (int j = 0; j < 5; j++)
{
mu.lock();
std::cout << "test2 j = " << j << std::endl;
mu.unlock();
}
}
/*
lock_guard locka(mu);
作用范围为从这一行开始,到那一次循环结束,还不用自己手动解锁。
*/
void test3()
{
for (int i = 0; i < 5; i++)
{
std::lock_guard locka(mu);
std::cout << "test3 i = " << i << std::endl;
}
}
void test4()
{
for (int j = 0; j < 5; j++)
{
std::lock_guard lock(mu);
std::cout << "test4 j = " << j << std::endl;
}
}
void test5()
{
for (int i = 0; i < 5; i++)
{
std::unique_lock locka(mu, std::defer_lock);
std::cout << "test5 i = " << i << std::endl;
locka.lock();
std::cout << "this is lock1" << std::endl;
}
}
void test6()
{
for (int j = 0; j < 5; j++)
{
std::unique_lock locka(mu);
std::cout << "test6 j = " << j << std::endl;
locka.unlock();
locka.lock();
std::cout << "this is lock2" << std::endl;
}
}
std::condition_variable cv;
bool print = false;
void test7()
{
for (int i = 0; i < 5; i++)
{
std::unique_lock l(mu);
std::cout << "test7 i = " << i << std::endl;
cv.notify_one();
print = true;
}
}
void test8()
{
for (int j = 0; j < 5; j++)
{
std::unique_lock l(mu);
if (!print)
{
cv.wait(l);
}
std::cout << "test8 j = " << j << std::endl;
print = false;
}
}
CRITICAL_SECTION section;//临界区变量
void test01()
{
for (int i = 0; i < 5; i++)
{
EnterCriticalSection(&section);//类似于 mutex.lock() 
std::cout << "this is test01 i = " << i << std::endl;
Sleep(1);
LeaveCriticalSection(&section);//类似于 mutex.unlock() 
}
}
void test02()
{
for (int j = 0; j < 5; j++)
{
EnterCriticalSection(&section);
std::cout << "this is test02 j = " << j << std::endl;
Sleep(1);
LeaveCriticalSection(&section);
}
}
HANDLE hmutex;
void test03()
{
for (int i = 0; i < 5; i++)
{
WaitForSingleObject(hmutex, INFINITE);//类似于mutex.lock() 阻塞等待多少时间 
std::cout << "test03 i = " << i << std::endl;
ReleaseMutex(hmutex);//类似于mutex.unlock() 释放互斥锁 
}
}
void test04()
{
for (int j = 0; j < 5; j++)
{
WaitForSingleObject(hmutex, INFINITE);
std::cout << "test04 j = " << j << std::endl;
ReleaseMutex(hmutex);
}
}
HANDLE hevent;
void test05()
{
for (int i = 0; i < 5; i++)
{
WaitForSingleObject(hevent, INFINITE);//类似于mutex.lock() 阻塞等待多少时间 
std::cout << "test05 i = " << i << std::endl;
SetEvent(hevent);//类似于mutex.unlock() 释放互斥锁 
}
}
void test06()
{
for (int j = 0; j < 5; j++)
{
WaitForSingleObject(hevent, INFINITE);
std::cout << "test06 j = " << j << std::endl;
SetEvent(hevent);
}
}
HANDLE sem;
void test07()
{
for (int i = 0; i < 5; i++)
{
WaitForSingleObject(sem, INFINITE);//类似于mutex.lock() 阻塞等待多少时间 
std::cout << "test07 i = " << i << std::endl;
ReleaseSemaphore(sem, 1, NULL);//类似于mutex.unlock() 释放互斥锁 
}
}
void test08()
{
for (int j = 0; j < 5; j++)
{
WaitForSingleObject(sem, INFINITE);
std::cout << "test08 j = " << j << std::endl;
ReleaseSemaphore(sem, 1, NULL);
}
}
int main(int argc, char const* argv[])
{
int i = 0; 
int rtn = 0;
int ret = 0;
char buff[100];
char *tmp = int2hex(82);
//read_csv2();//ok
//float num = 0.3;
//int result = ceil(num);
//printf("向上取整后的结果是:%d
", result);
--------------多线程-----START------------------------
//f_multi_thread();
//f_multiThread();//【Demo1】:创建一个最简单的线程
//f_multiThread2();//【Demo2】:在线程函数中传入参数
//f_multiThread3();//【Demo3】:线程同步
//售票系统 //
//Test2();//【Demo4】:模拟火车售票系统
====== C++11 线程库 ==== START ==========
//std::thread a;//创建线程1,定义线程,后面再分配任务
//a = std::thread(threadProc);
//std::thread b(threadProc2, 5);//创建线程2 ,定义线程的时候分配任务,参数类似于printf一样,可以为多个
//a.join();
//b.join();//采用join,主线程会阻塞等待子线程执行完毕
//std::thread c(threadProc3);
//c.detach();//采用detach,主线程不会等,这个线程开启早,还能输出到主线程的控制台
//std::cout << "main thread exit" << std::endl;
//std::thread d(threadProc4);
//d.detach();//
//std::thread a(test1);
//std::thread b(test2);
//a.join();
//b.join();
//std::cout << "main thread finish." << std::endl;
//std::thread a(test3);
//std::thread b(test4);
//a.join();
//b.join();
//std::cout << "main thread finish." <pTicket;
while (pSaleData->nCount > 0)
{
//请求获得一个互斥量锁
WaitForSingleObject(g_hMutex2, INFINITE);
if (pSaleData->nCount > 0)
{
std::cout <strThreadName << "出售第" <nCount-- <nCount >= 0) 
{
std::cout << "出票成功!剩余" <nCount << "张票." << std::endl;
}
else 
{
std::cout << "出票失败!该票已售完。" <赣州");
const int THREAD_NUMM = 2;//8;//
THD_DATA threadSale[THREAD_NUMM];
HANDLE hThread[THREAD_NUMM];
for (int i = 0; i < THREAD_NUMM; ++i)
{
threadSale[i].pTicket = &ticket;
std::string strThreadName = convertToString(i);
strThreadName = "窗口" + strThreadName;
strcpy(threadSale[i].strThreadName, strThreadName.c_str());
//创建线程
hThread[i] = CreateThread(NULL, NULL, SaleTicket, &threadSale[i], 0, NULL);
//请求获得一个互斥量锁
WaitForSingleObject(g_hMutex2, INFINITE);
std::cout << threadSale[i].strThreadName << "开始出售 " <strTicketName << " 的票..." << std::endl;
//释放互斥量锁
ReleaseMutex(g_hMutex2);
//关闭线程
CloseHandle(hThread[i]);
}
system("pause");
}

参考:

【Linux】多线程同步的四种方式 – 西*风 – 博客园 (cnblogs.com)

一文搞定c++多线程同步机制_c++多线程同步等待-CSDN博客

C++多线程同步总结 – 念秋 – 博客园 (cnblogs.com)

Linux 下多线程(C语言) | 大眼睛男孩儿 (zhangxiaoya.github.io)

读写锁 – 张飘扬 – 博客园 (cnblogs.com)

Linux C++多线程同步的四种方式(非常详细)-CSDN博客

本站无任何商业行为
个人在线分享 » C++多线程同步总结
E-->