zoukankan      html  css  js  c++  java
  • c++多线程编程:常见面试题

    题目:子线程循环 10 次,接着主线程循环 100 次,接着又回到子线程循环 10 次,接着再回到主线程又循环 100 次,如此循环50次,试写出代码

    子线程与主线程必有一个满足条件(flag == num),不满足条件的那个线程不可能获取unique_lock(会在wait中释放),只有满足条件的线程才能获取锁,执行程序

    mutex m;//保护条件的互斥访问
    condition_variable cond;//条件变量
    int flag = 10;//条件
    void fun(int num) {
        for (int i = 0; i<50; i++) {
            unique_lock<mutex> lk(m);//A unique lock is an object that manages a mutex object with unique ownership in both states: locked and unlocked.  
            while (flag != num)
                cond.wait(lk);//在调用wait时会执行lk.unlock()  
            for (int j = 0; j<num; j++)
                cout << j << " ";
            cout << endl;
            flag = (num == 10) ? 100 : 10;
            cond.notify_one();//被阻塞的线程唤醒后lk.lock()恢复在调用wait前的状态  
        }
    }
    int main() {
        thread child(fun, 10);
        fun(100);
        child.join();
        
        system("pause");
        return 0;
    }

    题目:编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。

    mutex m;
    condition_variable cond;
    int loop = 10;
    int flag = 0;
    
    void func(int id)
    {
        for (int i = 0; i < loop; ++i)
        {
            unique_lock<mutex> lk(m);
            while (flag != id)
                cond.wait(lk);
            cout << static_cast<char>('A' + id) << " ";
            flag = (flag + 1) % 3;
            cond.notify_all();
        }
    }
    
    void main()
    {
        thread A(func, 0);
        thread B(func, 1);
        func(2);
        cout << endl;
    
        A.join();
        B.join();
    
        system("pause");
    }

    题目(google笔试题):有四个线程1、2、3、4。线程1的功能就是输出1,线程2的功能就是输出2,以此类推.........现在有四个文件ABCD。初始都为空。现要让四个文件呈如下格式:
    A:1 2 3 4 1 2....
    B:2 3 4 1 2 3....
    C:3 4 1 2 3 4....

    D:4 1 2 3 4 1....

    mutex m;
    condition_variable cond;
    int loop = 10;
    int flag;
    
    void func(int num)
    {
        for (int i = 0; i < loop; ++i)
        {
            unique_lock<mutex> lk(m);
            while (num != flag)
                cond.wait(lk);
            cout << num + 1 << " ";
            flag = (flag + 1) % 4;
            cond.notify_all();
        }
    }
    
    void main(int argc,char *argv[])
    {
        flag = atoi(argv[1]);
        thread one(func, 1);
        thread two(func, 2);
        thread three(func, 3);
        func(0);
        one.join();
        two.join();
        three.join();
        cout << endl;
    
        system("pause");
    }

    读者写者问题

    这也是一个非常经典的多线程题目,题目大意如下:有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者读时写者也不能写。

    class rwlock {
    private:
        mutex _lock;
        condition_variable _wcon, _rcon;
        unsigned _writer, _reader;
        int _active;
    public:
        void read_lock() {
            unique_lock<mutex> lock(_lock);
            ++_reader;
            while (_active < 0 || _writer > 0)
                _rcon.wait(lock);
            --_reader;
            ++_active;
        }
        void write_lock() {
            unique_lock<mutex> lock(_lock);
            ++_writer;
            while (_active != 0)
                _wcon.wait(lock);
            --_writer;
            _active = -1;
        }
        void unlock() {
            unique_lock<mutex> lock(_lock);
            if (_active > 0) {
                --_active;
                if (_active == 0) _wcon.notify_one();
            }
            else {
                _active = 0;
                if (_writer > 0) _wcon.notify_one();
                else if (_reader > 0) _rcon.notify_all();
            }
    
        }
        rwlock() :_writer(0), _reader(0), _active(0) {
        }
    };
    
    void t1(rwlock* rwl) {
        while (1) {
            cout << "I want to write." << endl;
            rwl->write_lock();
            cout << "writing..." << endl;
            this_thread::sleep_for(chrono::seconds(5));
            rwl->unlock();
            this_thread::sleep_for(chrono::seconds(5));
        }
    }
    
    void t2(rwlock* rwl) {
        while (1) {
            cout << "t2-I want to read." << endl;
            rwl->read_lock();
            cout << "t2-reading..." << endl;
            this_thread::sleep_for(chrono::seconds(1));
            rwl->unlock();
        }
    }
    
    void t3(rwlock* rwl) {
        while (1) {
            cout << "t3-I want to read." << endl;
            rwl->read_lock();
            cout << "t3-reading..." << endl;
            this_thread::sleep_for(chrono::seconds(1));
            rwl->unlock();
        }
    }
    
    int main()
    {
        rwlock* rwl = new rwlock();
        thread th1(t1, rwl);
        thread th2(t2, rwl);
        thread th3(t3, rwl);
        th1.join();
        th2.join();
        th3.join();
    
        system("pause");
        return 0;
    }

    线程安全的queue

    STL中的queue是非线程安全的,一个组合操作:front(); pop()先读取队首元素然后删除队首元素,若是有多个线程执行这个组合操作的话,可能会发生执行序列交替执行,导致一些意想不到的行为。因此需要重新设计线程安全的queue的接口。

    template<typename T>
    class threadsafe_queue
    {
    private:
        mutable std::mutex mut;
        std::queue<T> data_queue;
        std::condition_variable data_cond;
    public:
        threadsafe_queue() {}
        threadsafe_queue(threadsafe_queue const& other)
        {
            std::lock_guard<std::mutex> lk(other.mut);
            data_queue = other.data_queue;
        }
        void push(T new_value)//入队操作  
        {
            std::lock_guard<std::mutex> lk(mut);
            data_queue.push(new_value);
            data_cond.notify_one();
        }
        void wait_and_pop(T& value)//直到有元素可以删除为止  
        {
            std::unique_lock<std::mutex> lk(mut);
            data_cond.wait(lk, [this] {return !data_queue.empty(); });
            value = data_queue.front();
            data_queue.pop();
        }
        std::shared_ptr<T> wait_and_pop()
        {
            std::unique_lock<std::mutex> lk(mut);
            data_cond.wait(lk, [this] {return !data_queue.empty(); });
            std::shared_ptr<T> res(std::make_shared<T>(data_queue.front()));
            data_queue.pop();
            return res;
        }
        bool try_pop(T& value)//不管有没有队首元素直接返回  
        {
            std::lock_guard<std::mutex> lk(mut);
            if (data_queue.empty())
                return false;
            value = data_queue.front();
            data_queue.pop();
            return true;
        }
        std::shared_ptr<T> try_pop()
        {
            std::lock_guard<std::mutex> lk(mut);
            if (data_queue.empty())
                return std::shared_ptr<T>();
            std::shared_ptr<T> res(std::make_shared<T>(data_queue.front()));
            data_queue.pop();
            return res;
        }
        bool empty() const
        {
            std::lock_guard<std::mutex> lk(mut);
            return data_queue.empty();
        }
    };

    题目:编写程序完成如下功能:

    1)有一int型全局变量g_Flag初始值为0

    2) 在主线称中起动线程1,打印“this is thread1”,并将g_Flag设置为1

    3) 在主线称中启动线程2,打印“this is thread2”,并将g_Flag设置为2

    4) 线程序1需要在线程2退出后才能退出

    5) 主线程在检测到g_Flag从1变为2,或者从2变为1的时候退出

    atomic<int> flag(0);
    
    void worker1(future<int> fut) 
    {//线程1  
        printf("this is thread1
    ");
        flag = 1;
        fut.get();//线程1阻塞至线程2设置共享状态  get等待异步操作结束并返回结果
        printf("thread1 exit
    ");
    }
    
    void worker2(promise<int> prom) 
    {//线程2  
        printf("this is thread2
    ");//C++11的线程输出cout没有boost的好,还是会出现乱序,所以采用printf,有点不爽  
        flag = 2;
        prom.set_value(10);//线程2设置了共享状态后,线程1才会被唤醒  
        printf("thread2 exit
    ");
    }
    
    //利用promise future来控制线程退出的次序
    int main()
    {
        promise<int> prom;
        future<int> fut = prom.get_future();
        thread one(worker1, move(fut));//注意future和promise不允许拷贝,但是具备move语义  
        thread two(worker2, move(prom));
        while (flag.load() == 0);
      ///将本线程从调用线程中分离出来,允许本线程独立执行 one.detach(); two.detach();
    //exit(1);//主线程到这里退出 printf("main thread exit "); system("pause"); return 0; }

    http://blog.csdn.net/liuxuejiang158blog/article/details/22300081

  • 相关阅读:
    数组中的逆序对★★
    把数组排成最小的数★★★
    丑数★★★
    整数中1出现的次数(从1到n整数中1出现的次数)
    连续子数组的最大和
    每两个字符串中插入字符串
    linux R环境安装以及注意事项
    JAVA调用R脚本 windwos路径下
    springboot 配置多数据源
    springboot 在配置文件写参数注入到类中
  • 原文地址:https://www.cnblogs.com/ljygoodgoodstudydaydayup/p/5950400.html
Copyright © 2011-2022 走看看