【问题标题】:Infinite loop multi-threading无限循环多线程
【发布时间】:2016-02-19 17:38:23
【问题描述】:

我已经编写了这个生产者/消费者问题解决方案。除了无限循环之外,它似乎正在工作。我的印象是pthread_exit(NULL); 会让它停止,但老实说,我已经迷失了方向。有人可以指出如何停止循环的正确方向吗?

#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<iostream>
#include<semaphore.h>

#define BUFFSIZE 10

using namespace std;

int buffer[BUFFSIZE];
int size; //current buffer size
int n = 0, m = 0;

pthread_mutex_t Mutex = PTHREAD_MUTEX_INITIALIZER;

sem_t Available;
sem_t Buffer; //indicates if buffer is full

//----------------------------------------------------------------//

void *Consumers(void *argument)
{
    int con_id = *((int *) argument);
    while(1)
    {
        if(size == 0)
        {
            cout << "Queue is empty." << endl;
        }

        sem_wait(&Available);
        pthread_mutex_lock(&Mutex);

        size--;
        cout << "Con " << con_id << ": Product removed from buffer" << endl;
        //for(int i = 0; i < size; i++)
        //{
        //  cout << Buffer[i] << " ";
        //}
        cout << endl;
        pthread_mutex_unlock(&Mutex);
        sem_post(&Buffer);
    }
    return(NULL);
}

//----------------------------------------------------------------//

void *Producers(void *argument)
{
    int item = 8;
    int pro_id = *((int *) argument);

    while(1)
    {
        sem_wait(&Buffer);
        pthread_mutex_lock(&Mutex);
        //Buffer[size] = item;
        cout << "Item added" << endl;
        size++;
        pthread_mutex_unlock(&Mutex);
        sem_post(&Available);
    }
    return(NULL);
}

//----------------------------------------------------------------//

int main()
{

    cout << "Enter number of producers: " << endl;
    scanf("%d", &n);
    cout << "Enter number of consumers: " << endl;
    scanf("%d", &m);
    //get number of producers(int n), and consumers(int m)
    sem_init(&Available, 0, 0);
    sem_init(&Buffer, 0, BUFFSIZE);

    pthread_t *con = new pthread_t[m];
    int *thread_args_c = new int[m];
    for(int i = 0; i < n; i++)
    {
        thread_args_c[i] = i;
        pthread_create(&con[i], NULL, Consumers, (void*) &i);
    }

    pthread_t *pro = new pthread_t[n];
    int *thread_args_p = new int[n];
    for(int i = 0; i < n; i++)
    {
        thread_args_p[i] = i;
        pthread_create(&pro[i], NULL, Producers, (void*) &i);
        pthread_join(con[i], NULL);
    }

    pthread_exit(NULL);

}

【问题讨论】:

  • main()s int i 变量上的数据竞争,其地址被传递给从它们读取的线程,而main() 修改它们。此外,&amp;ii 的生命周期结束后使用。

标签: c++ multithreading pthreads infinite-loop producer-consumer


【解决方案1】:

不确定您的期望。 pthread_exit 出现在 main 的末尾(并且完全不需要在那里,因为 main 无论如何都会退出),但是你在线程内的 enless 循环永远不会让 main 达到这一点(因为你正在加入消费者线程)。

另外,您的创建和加入模型意义不大 - 在创建生产者之后加入消费者线程有什么意义?

最后,但不是租约,您未能加入生产者线程。

【讨论】:

    【解决方案2】:

    循环不会停止,因为代码中没有实际退出循环的逻辑。

    进程卡住了,因为pthread_join 暂停了调用线程,直到目标退出。见documentation for pthread_join

    如果您不关心实际终止线程并返回主线程,只需删除对pthread_join 的调用。由于主线程退出,进程应该终止。

    要真正正确地终止循环,您需要设置内部或外部触发器。您可以在一定次数的迭代后在内部退出循环。为此,您将使用while(x&lt;=y) 而不是while(1)

    你也可以让它变得更复杂,让主线程在外部向其他线程发出信号,它希望其他线程关闭。当您准备退出时,您可以让主线程设置一个 (volatile) 布尔值,并让其他线程 break 基于它的循环。如果您关心出口的Atomicity,则需要用锁保护布尔值。

    【讨论】:

    • 关于布尔值的答案并不完整。
    • @SergeyA 这回答了“如何停止循环”的原始问题。我认为没有必要详细介绍停止信号如何同步以实现原子性。这可能本身就是一个问题,可能已经在其他地方得到了回答。
    • 你还提到了锁!有人可能会同意,如果你不想要退出的原子性,你可以使用一个简单的布尔值。这是你的消息吗?
    • @SergeyA 是的,这就是我的意思。如果一个人不关心在发出停止信号后立即退出线程,那么不妨使用全局布尔值。线程最终将读取全局变量的更新值并退出。否则,您可能希望了解自己可以使用的各种同步机制。
    • 线程最终会读取全局变量的更新值这是错误的。
    猜你喜欢
    • 1970-01-01
    • 2014-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-13
    • 2019-04-12
    • 2012-11-14
    相关资源
    最近更新 更多