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…

请设计程序。 [讲解:https://www.cnblogs.com/waterfall/p/7994384.html]


#include <thread>
#include <vector>
#include <condition_variable>
#include <mutex>
#include <map>

#include <semaphore.h>

#define MaxThreadNums 4
#define MaxCycleNums 7

namespace me {
    class Semaphore {
    public:
        Semaphore(long count = 0)
                : count_(count) {
        }

        void signal() {
            std::unique_lock<std::mutex> lock(mutex_);
            ++count_;
            cv_.notify_one();
        }

        void wait() {
            std::unique_lock<std::mutex> lock(mutex_);
            cv_.wait(lock, [=] { return count_ > 0; });
            --count_;
        }

    private:
        std::mutex mutex_;
        std::condition_variable cv_;
        long count_;
    };
}

class File {
public:
    File() {}

    void Write(char c) {
        std::unique_lock<std::mutex> Guard(mtx_);
        buffer_ += c;
    }

    std::string GetBuffer() {
        std::unique_lock<std::mutex> Guard(mtx_);
        return buffer_;
    }

private:
    std::mutex mtx_;
    std::string name_;
    std::string buffer_;
    size_t pos_;
};

/*
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....
 */

#if 10

#define sem_init

me::Semaphore sem_a{1};
me::Semaphore sem_b{1};
me::Semaphore sem_c{1};
me::Semaphore sem_d{1};

me::Semaphore *sems[] = {&sem_a, &sem_b, &sem_c, &sem_d};

#else
sem_t sem_a;
sem_t sem_b;
sem_t sem_c;
sem_t sem_d;

sem_t *sems[] = {&sem_a, &sem_b, &sem_c, &sem_d};

#endif

int sem_wait(me::Semaphore *sem) {
    sem->wait();
    return 0;
}

int sem_post(me::Semaphore *sem) {
    sem->signal();
    return 0;
}

using ThreadTag = uint8_t;
using PosIdx = uint8_t ;

class ThreadInfo {
public:
    ThreadInfo(ThreadTag id) : id_(id) {

    }

    void WriteToFile(File &file) {
        file.Write(GetData());
    }

    uint8_t GetId() {
        return id_;
    }

    char GetData() {
        return '1' + id_;
    }

private:
    ThreadTag id_;
};

class WriteHelper {
public:
    explicit WriteHelper(ThreadInfo &info) {
        pos_ = GetInitPosIndex(info.GetId());
    }

    File &GetFileHandler() {
        uint8_t idx = index_[pos_++ % MaxThreadNums];
        return GetFiles()[idx];
    }

private:
    PosIdx index_[4] = {0, 3, 2, 1};
    PosIdx pos_;

public:
    static PosIdx GetInitPosIndex(ThreadTag id) {
        thread_local std::map<ThreadTag, PosIdx> map_;
        if (map_.empty()) {
            // thread -> init index
            map_[0] = 0;
            map_[1] = 3;
            map_[2] = 2;
            map_[3] = 1;
        }

        return map_[id];
    }

    static File *GetFiles() {
        static File files_[MaxThreadNums];
        return files_;
    }
};

// th sched: A -> B -> C -> D
void fun(ThreadInfo info) {

    WriteHelper helper(info);

    for (int i = 0; i < MaxCycleNums; i++) {
        sem_wait(sems[info.GetId()]);

        // printf("my_name: %c, %d\n", info.GetId(), info.GetData());
        info.WriteToFile(helper.GetFileHandler());

        sem_post(sems[(info.GetId() + 1) % MaxThreadNums]);
    }

}

int main() {
    sem_init(&sem_a, 0, 1);
    sem_init(&sem_b, 0, 1);
    sem_init(&sem_c, 0, 1);
    sem_init(&sem_d, 0, 1);

    std::thread ths[MaxThreadNums];

    for (int i = 0; i < MaxThreadNums; ++i) {
        ths[i] = std::thread(fun, ThreadInfo(i));
    }

    for (int i = 0; i < MaxThreadNums; ++i) {
        auto &th = ths[i];
        if (th.joinable()) {
            th.join();
            // printf("exit th:%d\n", i);
        }
    }

    for (int i = 0; i < MaxThreadNums; ++i) {
        auto buf = WriteHelper::GetFiles()[i].GetBuffer();
        printf("buf %c: %s\n", i + 'A', buf.c_str());
    }

    printf("\nmain is over\n");
}


在这里插入图片描述🔗

备份地址: 【【Google面试题】有四个线程1、2、3、4同步写入数据…C++11实现