一次性创建多个线程、互斥量、死锁

  • 一、创建和等待多个线程:
    a)多个线程执行程序是乱的,跟操作系统内部对线程的运行调度机制有关
    b)主线程等待所有子线程运行结束后,最后主线程结束,推荐使用join,更容易写出稳定的程序
    c)把thread对象放入容器里,便于管理
  • 二、数据共享问题
    a)只读的数据:是安全稳定的,不需要特别的处理手段,直接读就可以
    b)有读有写:如果代码没有特别处理,程序必然崩溃。 最简单的处理方法是,读的时候不能写,写的时候不能读,所有写的线程不能同时写,所有读的线程不能同时读;
    c) 保护共享数据:操作时,某个线程用代码把共享数据锁住、操作数据、解锁, 其他想操作共享数据的线程必须等待解锁,锁定、操作、解锁
  • 三、互斥量(mutex)的基本概念:
    a)互斥量是一个类对象。理解成一把锁,多个线程尝试用lock()成员函数来加锁,只能有个线程能锁定成功(成功的线程才对内存具有操作权限),如果没成就会卡在lock这里不断尝试。
    b)互斥量使用要小心,保护数据不多也不少,少了,没达到保护效果,多了影响效率。
    c)互斥量用法:先lock(),操作共享数据,unlock,lock()与unlock()要成对使用,每调用一次lock()就必须调用一次unlock()
    d)std::lock_guard():可以替代lock()与unlock(),也就是说,用了lock_guard之后就不用再使用lock()与unlock()
    e)lock_guard每次到return才执行unlock的功能,如果想让lock_guard提前结束,可以用{…}
  • 四、死锁
    • 原因:
      a)两个互斥量,上锁顺序不一致,线程A先mutex1上锁然后mutex2上锁,线程B先mutex2上锁然后mutex1上锁。
      b)当线程 mutex1上锁之后,需要进行mutex2上锁,但此时,线程B正处于mutex2上锁状态,因此线程A无法向下运行。
      c)当线程 mutex2上锁之后,需要进行mutex1上锁,但此时,线程A正处于mutex1上锁状态,因此线程B无法向下运行。
      d)形成两个线程都无法向下运行的局面
    • 解决方案:
      a)只要保证这两个互斥量上锁的顺序一致就不会死锁
      b)使用std::lock()一次性锁住多个互斥量,例std::lock(mutex1,mutex2),如果其中有一个没有锁住,则会把另外锁住的也放开,不会造成死锁现象。
      c)使用std::lock()必须单独手动调用mutex1.unlock()函数解锁
      d)或者在调用std::lock()后,紧接着使用std::lock_guardstd::mutex myguard(mutex1,std::adopt::lock),adopt::lock会自动释放互斥量
#include <iostream>
#include <thread>
#include <vector>
#include <iterator>
#include <list>
#include <mutex>
using namespace std;

void myPrint(int  num)
{
    cout << "Thread  " << num << "  is  beginnig!" << "  Thread_ID= " << std::this_thread::get_id() << endl;
    for(int i=0;i<1000000;i++)
    {
        cout<<num<<endl;
    }
    cout << "Thread  " <<num << "  is  over" << "  Thread_ID= " << std::this_thread::get_id() << endl;
}

class A {

public:
    void myPrint_A(int  num)
    {

        cout << "Thread  " << (char)num << "  is  beginnig!" << "  Thread_ID= " << std::this_thread::get_id() << endl;
        for(int i=0;i<1000000;i++)
        {
            myMutex1.lock();
            myMutex2.lock();
            cout<<(char)num<<endl;
             myMutex2.unlock();
             myMutex1.unlock();
        }
        cout << "Thread  " <<(char) num << "  is  over" << "  Thread_ID= " << std::this_thread::get_id() << endl;
    }

    void myPrint_B(int num)
    {
        cout << "Thread  " << (char)num << "  is  beginnig!" << "  Thread_ID= " << std::this_thread::get_id() << endl;
        for(int i=0;i<1000000;i++)
        {
            myMutex2.lock();
            myMutex1.lock();
            cout<<(char)num<<endl;
            myMutex1.unlock();
            myMutex2.unlock();
        }
        cout << "Thread  " << (char)num << "  is  over" << "  Thread_ID= " << std::this_thread::get_id() << endl;
    }

    void myPrint_C(int  num)
    {

        cout << "Thread  " << (char)num << "  is  beginnig!" << "  Thread_ID= " << std::this_thread::get_id() << endl;
        for(int i=0;i<1000000;i++)
        {
           std::lock(myMutex1, myMutex2);
            cout<<(char)num<<endl;
             myMutex2.unlock();
             myMutex1.unlock();
        }
        cout << "Thread  " <<(char) num << "  is  over" << "  Thread_ID= " << std::this_thread::get_id() << endl;
    }

    void myPrint_D(int num)
    {
        cout << "Thread  " << (char)num << "  is  beginnig!" << "  Thread_ID= " << std::this_thread::get_id() << endl;
        for(int i=0;i<1000000;i++)
        {
            std::lock(myMutex1, myMutex2);

            cout<<(char)num<<endl;
            myMutex1.unlock();
            myMutex2.unlock();
        }
        cout << "Thread  " << (char)num << "  is  over" << "  Thread_ID= " << std::this_thread::get_id() << endl;
    }

    void writeMsg()
    {
        cout << "writeMsgthis  " << this << endl;
        cout << "writeMsgmsgQueue_addr   " << &(this->msgQueue) << endl;
        cout << "Thread   writeMsg()  is  beginnig!" << "  Thread_ID= " << std::this_thread::get_id() << endl;
        for (int i=0; i<1000000000; i++)
        {
            cout << "Write  " << i << "  to msgQueue" << endl;
            myMutex.lock();
            msgQueue.push_back(i);
            myMutex.unlock();
        }
        cout << "Thread   writeMsg()  is  over!" << "  Thread_ID= " << std::this_thread::get_id() << endl;
    }

    void readMsg()
    {
        cout << "readMsg_this  " << this << endl;
        cout << "readMsgmsgQueue_addr   " << &(this->msgQueue) << endl;
        cout << "Thread   readMsg()  is  beginnig!" << "  Thread_ID= " << std::this_thread::get_id() << endl;
        for (int i = 0; i<1000000000; i++)
        {
            if (!msgQueue.empty())
            {
                {
                    std::lock_guard<std::mutex> myLockGuard(myMutex);
                    int cmd = msgQueue.front();
                    cout << "read the first one in msgQueue is  " << cmd << endl;
                    msgQueue.pop_front();
                }  //如果不用大括号,则在return处执行unlock

            }
            else {
                cout << "msgQueue is empty,i=  " << i << endl;
            }
        }
        cout << "Thread   readMsg()  is  over!" << "  Thread_ID= " << std::this_thread::get_id() << endl;
    }
private:
    list<int> msgQueue;
    mutex myMutex;
    mutex myMutex1;
    mutex myMutex2;
};

//一次性创建多个线程
void example1()
{

    vector<thread> myThread;

    for (int i = 0; i<10; i++)
    {
        myThread.push_back(thread(myPrint, i));
    }
    for (vector<thread>::iterator iter = myThread.begin(); iter != myThread.end(); iter++)
    {
        iter->join();
    }

}

//互斥量
void example2()
{
    A myobj;

    thread writeThread(&A::writeMsg, &myobj);
    thread readThread(&A::readMsg, &myobj);
    writeThread.join();
    readThread.join();

}

//死锁
void example3()
{
    A myobj;
    thread Thread_A(&A::myPrint_A,&myobj,(int) 'A');
    thread Thread_B(&A::myPrint_B,&myobj, (int)'B');
    Thread_A.join();
    Thread_B.join();
}

//死锁
void example4()
{
    A myobj;
    thread Thread_A(&A::myPrint_C,&myobj,(int) 'C');
    thread Thread_B(&A::myPrint_D,&myobj, (int)'D');
    Thread_A.join();
    Thread_B.join();

}

int main()
{
    cout << "Main thread is begining!" << endl;
//    example1();
//    example2();
    example4();
    cout << "Main thread is over!" << endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值