C++ 在使用Poco多线程时,如何使用信号量来确保顺序?

C++ 在使用Poco多线程时,如何使用信号量来确保顺序?,c++,multithreading,semaphore,poco-libraries,C++,Multithreading,Semaphore,Poco Libraries,我正在编写一个简单的程序来演示信号量的使用。(稍后测试自定义编写的信号量是否有效) 我有4个线程同时运行一个函数。每个函数等待的时间都是随机的,然后打印:Hello,world!这是线程n我睡了uSuS 正如您所期望的,消息以随机顺序打印到标准输出。这表明线程是并发运行的,因为如果它们按顺序执行,它们将按顺序出现 在这个演示中,我想使用一个信号量来强制执行命令。但是,它目前不起作用 这是我的密码: sem = sem_open("mutex" , O_CREAT | O_RDWR , S_IRW

我正在编写一个简单的程序来演示信号量的使用。(稍后测试自定义编写的信号量是否有效)

我有4个线程同时运行一个函数。每个函数等待的时间都是随机的,然后打印:
Hello,world!这是线程
n
我睡了
uS
uS

正如您所期望的,消息以随机顺序打印到标准输出。这表明线程是并发运行的,因为如果它们按顺序执行,它们将按顺序出现

在这个演示中,我想使用一个信号量来强制执行命令。但是,它目前不起作用

这是我的密码:

sem = sem_open("mutex" , O_CREAT | O_RDWR , S_IRWXU | S_IRWXG | S_IRWXO, 1); // name, oflag, mode, initial value

Poco::Thread thread[5];

class HelloRunnable: public Poco::Runnable
{
public:
    HelloRunnable(int arg) //constructor for the runnable
    {
        n = arg;
    }

    int n;

    virtual void run() //entry point for the threads
    {
        sem_wait(sem); //the semaphore
            timeval t;
            gettimeofday(&t, NULL);
            srand(t.tv_usec * t.tv_sec);
            int uS = rand()%100000;
            usleep(uS); //sleep for random length of time

            std::cout << "Hello, world! This is thread " << n << " I slept for "<< uS << "uS" <<std::endl;
        sem_post(sem);
        return;
    }
};



int main()
{
    HelloRunnable runnable1(1); //construct a runnable with arg = 1
    thread[1].start(runnable1); //execute that runnable

    HelloRunnable runnable2(2); //construct a runnable with arg = 2
    thread[2].start(runnable2); //execute that runnable

    HelloRunnable runnable3(3); //...
    thread[3].start(runnable3);

    HelloRunnable runnable4(4);
    thread[4].start(runnable4);

    //wait for all threads to finish
    thread[1].join();
    thread[2].join();
    thread[3].join();
    thread[4].join();

    return 0;
}
我应该在代码中的何处放置信号量,以确保消息按顺序打印?如果这很简单,我道歉。我不是有编码背景的

编辑


我将
sem\u wait
移动到
usleep
之前。现在它工作得更好,但不是所有的时间。它在大约%45的时间内按顺序打印,在大约45%的时间内按相反顺序打印,在大约%10的时间内按随机顺序打印。这是为什么

原因是sem_wait中阻塞的线程以不可预知的顺序被唤醒。此外,你增加了一些随机睡眠时间,增加了更多的混乱

事实上,每个线程需要一个信号量。 线程n应该sem\u post信号量n+1,然后sem\u wait信号量n。 最后一个线程应该sem\u post信号量0,依此类推。 只需在一个数组中创建信号量,第一个数组的初始值为1,另一个数组的初始值为0。线程参数可以是访问线程中正确信号量的索引

#include <Poco/Thread.h>

#include <iostream>

#include <semaphore.h>
#include <sys/time.h>
#include <unistd.h>

#define THREADS 5
#define LOOPS 5

sem_t semaphores[THREADS];

class HelloRunnable: public Poco::Runnable {
public:
    HelloRunnable(unsigned int index) {
        _index = index;
        // Seed random generator
        timeval time;
        gettimeofday(&time, NULL);
        srand(time.tv_usec * time.tv_sec);
    }

    virtual void run() {
        for (unsigned int loop = 0; loop < LOOPS; ++loop) {
            // Wait
            sem_wait(&semaphores[_index]);
            // Sleep random time
            int sleep = rand() % 100000;
            usleep(sleep);
            // Output
            std::cout << "Hello, world! This is thread " << _index
                    << " in loop " << loop << " I slept for " << sleep << "µS"
                    << std::endl;
            // Unlock next thread
            sem_post(&semaphores[(_index + 1) % THREADS]);
        }
        return;
    }
private:
    unsigned int _index;
};

int main() {
    HelloRunnable *runnables[THREADS];
    Poco::Thread *threads[THREADS];

    // Initialize semaphores and create threads and runnables
    for (unsigned int index = 0; index < THREADS; ++index) {
        sem_init(&semaphores[index], 0, index ? 0 : 1);
        threads[index] = new Poco::Thread();
        runnables[index] = new HelloRunnable(index);
    }

    // Start threads
    for (unsigned int index = 0; index < THREADS; ++index) {
        threads[index]->start(*runnables[index]);
    }

    // Wait for all threads to finish
    for (unsigned int index = 0; index < THREADS; ++index) {
        threads[index]->join();
    }

    // Cleanup
    for (unsigned int index = 0; index < THREADS; ++index) {
        free(runnables[index]);
        free(threads[index]);
    }
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#定义线程5
#定义循环5
sem_t信号量[线程];
类HelloRunnable:公共Poco::Runnable{
公众:
HelloRunnable(无符号整数索引){
_指数=指数;
//种子随机发生器
timeval时间;
gettimeofday(&time,NULL);
srand(time.tv_usec*time.tv_sec);
}
虚拟空运行(){
for(无符号整数循环=0;循环<循环;++循环){
//等等
sem_wait(&信号量[_索引]);
//睡眠随机时间
int sleep=rand()%100000;
usleep(睡眠);
//输出

std::cout原因是sem_wait中阻塞的线程以不可预测的顺序被唤醒。此外,您添加了一些随机睡眠时间,增加了更多的混乱

事实上,每个线程需要一个信号量。 线程n应该sem\u post信号量n+1,然后sem\u wait信号量n。 最后一个线程应该sem\u post信号量0,依此类推。 只需在一个数组中创建信号量,第一个数组的初始值为1,另一个数组的初始值为0。thread参数可以是访问线程中正确信号量的索引

#include <Poco/Thread.h>

#include <iostream>

#include <semaphore.h>
#include <sys/time.h>
#include <unistd.h>

#define THREADS 5
#define LOOPS 5

sem_t semaphores[THREADS];

class HelloRunnable: public Poco::Runnable {
public:
    HelloRunnable(unsigned int index) {
        _index = index;
        // Seed random generator
        timeval time;
        gettimeofday(&time, NULL);
        srand(time.tv_usec * time.tv_sec);
    }

    virtual void run() {
        for (unsigned int loop = 0; loop < LOOPS; ++loop) {
            // Wait
            sem_wait(&semaphores[_index]);
            // Sleep random time
            int sleep = rand() % 100000;
            usleep(sleep);
            // Output
            std::cout << "Hello, world! This is thread " << _index
                    << " in loop " << loop << " I slept for " << sleep << "µS"
                    << std::endl;
            // Unlock next thread
            sem_post(&semaphores[(_index + 1) % THREADS]);
        }
        return;
    }
private:
    unsigned int _index;
};

int main() {
    HelloRunnable *runnables[THREADS];
    Poco::Thread *threads[THREADS];

    // Initialize semaphores and create threads and runnables
    for (unsigned int index = 0; index < THREADS; ++index) {
        sem_init(&semaphores[index], 0, index ? 0 : 1);
        threads[index] = new Poco::Thread();
        runnables[index] = new HelloRunnable(index);
    }

    // Start threads
    for (unsigned int index = 0; index < THREADS; ++index) {
        threads[index]->start(*runnables[index]);
    }

    // Wait for all threads to finish
    for (unsigned int index = 0; index < THREADS; ++index) {
        threads[index]->join();
    }

    // Cleanup
    for (unsigned int index = 0; index < THREADS; ++index) {
        free(runnables[index]);
        free(threads[index]);
    }
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#定义线程5
#定义循环5
sem_t信号量[线程];
类HelloRunnable:公共Poco::Runnable{
公众:
HelloRunnable(无符号整数索引){
_指数=指数;
//种子随机发生器
timeval时间;
gettimeofday(&time,NULL);
srand(time.tv_usec*time.tv_sec);
}
虚拟空运行(){
for(无符号整数循环=0;循环<循环;++循环){
//等等
sem_wait(&信号量[_索引]);
//睡眠随机时间
int sleep=rand()%100000;
usleep(睡眠);
//输出
标准::cout