Reconfiguration of printing {0, 1, 2, 3} by a multi-threaded program (C ++)

I want to print the permutation {0, 1, 2, 3} given by a multithreaded program written in C ++ 11.

Source:

#include <iostream>
#include <stdio.h>
#include <thread>
#include <vector>
#include <chrono>

using namespace std;


void func(int index);

int main()
{
    vector<thread> threads;

    for (int i = 0; i < 4; i++)
    {
        auto var = [&]()
        {
            return func(i);
        };

        threads.push_back(thread(var));
    }

    for (auto& thread : threads)
        thread.join();
}

void func(int index)
{
    cout << index;

    for (int i = 0; i < 10000; i++);
}

I expect that in the output there will be a permutation of 0123, but I get strange results, for example:

0223

0133

0124

I do not understand this strange behavior, in particular, I can not explain the presence of the number 4.

Perhaps this is a beginner's mistake, I thank everyone that will help me.

+4
source share
3 answers

You write idown the link:

    auto var = [&]()
    {
        return func(i);
    };

, , , , , i, , i.

, . , , . i, , , , .

, , i , for , undefined.

+5

undefined :

-, , , i, .

[edit: no-longer true ++ 11] -, cout.

- , . [edit:] , cout .

?

, .

#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <chrono>
#include <queue>

class LockedQueue {
    std::queue<int> queue_;
    mutable std::mutex mutex_;
public:
    LockedQueue() = default;

    // these don't have to be deleted, but you'd have to decide whether or
    // not each operation needed to invoke a lock, and in the case of operator=
    // you have two mutexes to contend with.
    LockedQueue(const LockedQueue&) = delete;
    LockedQueue(LockedQueue&&) = delete;
    LockedQueue& operator=(const LockedQueue&) = delete;
    LockedQueue& operator=(LockedQueue&&) = delete;

    void push(int value) {
        std::lock_guard<std::mutex> lock(mutex_);
        queue_.push(value);
    }
    int pop() {
        std::lock_guard<std::mutex> lock(mutex_);
        int value = queue_.front();
        queue_.pop();
        return value;
    }
    bool empty() const {
        std::lock_guard<std::mutex> lock(mutex_);
        return queue_.empty();
    }
};

void func(LockedQueue& work, LockedQueue& results);

int main()
{
    LockedQueue work, results;
    std::vector<std::thread> threads;

    for (int i = 0; i < 4; i++)
    {
        work.push(i);
        threads.emplace_back(func, std::ref(work), std::ref(results));
    }

    for (auto& thread : threads)
        thread.join();

    while (!results.empty()) {
        int i = results.pop();
        std::cout << i;
    }
}

void func(LockedQueue& work, LockedQueue& results)
{
    int index = work.pop();
    using namespace std::chrono_literals;
    std::this_thread::sleep_for(1s);
    results.push(index);
}

http://ideone.com/7G0JEO

- , : , , 0 , , 1, 2 3 , .

+2

i, , , , i , :

threads[i].join();

:

for (auto& thread : threads)
    thread.join();

:

int main()
{
    vector<thread> threads;

    for (int i = 0; i < 4; i++)
    {

        auto var = [&]()
        {
            return func(i);
        };

        threads.push_back(thread(var));

        threads[i].join(); // joining the thread after its creation.
    }

    system("pause");
    return 0;
}

.

+1

Source: https://habr.com/ru/post/1651906/


All Articles