【问题标题】:c++ pthreads opertions on a global char bufferc++ pthreads 对全局字符缓冲区的操作
【发布时间】:2014-04-03 02:48:45
【问题描述】:

我正在试验 pthreads。我正在尝试创建三个线程并让它们在全局字符缓冲区上运行。我正在为其关键部分使用互斥锁和解锁。程序流程应该是: Main 产生三个线程。线程一锁定,初始化缓冲区,打印出来,通知线程二,然后解锁。线程二进入其临界区,对缓冲区进行操作并向线程三发出信号,等等。有时它似乎可以工作。其他时候,它似乎被自旋锁吸住了。在正确方向上的任何帮助都会很棒。谢谢。

#include <pthread.h>  
#include <string.h>  
#include <unistd.h>  
#include <iostream>

using namespace std;

const int num_threads = 3;

char buffer[100]; 
pthread_mutex_t buffer_mutex = pthread_mutex_initializer; 
pthread_cond_t buffer_cond = pthread_cond_initializer;



void* firstthreadfunc(void* proc) { 
    string a = "data received";
    pthread_mutex_lock(&buffer_mutex);

    sleep(1);
    cout<<"threadone"<<endl;    
    for(int i = 0;i<14;i++){
        buffer[i] = a[i];
        cout<<buffer[i];
    }
    cout<<endl;

    pthread_cond_signal(&buffer_cond);   

    pthread_mutex_unlock(&buffer_mutex);
    return null; 
} 

void* secondthreadfunc(void* proc) { 
    string a = "data processed"; 

    pthread_mutex_lock(&buffer_mutex);
    pthread_cond_wait(&buffer_cond, &buffer_mutex);

    sleep(1);
    cout<<"threadtwo"<<endl;        
    for(int i = 0; i<15 ;i++){
        buffer[i] = a[i];
        cout<<buffer[i];
    }   
    cout<<endl;  

    pthread_cond_signal(&buffer_cond);
    pthread_mutex_unlock(&buffer_mutex);
    return null; 
}

void* thirdthreadfunc(void* proc) { 

    string a = "data sent";
    pthread_mutex_lock(&buffer_mutex);
    pthread_cond_wait(&buffer_cond, &buffer_mutex); 
    sleep(1);

    cout<<"thread three"<<endl;
    for(int i = 0;i<9;i++){
        buffer[i] = a[i];
        cout<<buffer[i];
    }
    cout<<endl;

    pthread_cond_signal(&buffer_cond);
    pthread_mutex_unlock(&buffer_mutex);
    return null; 
}


int main() {

    pthread_t  p_threadone, p_threadtwo, p_threadthree;;

    pthread_attr_t attr;
    pthread_attr_init(&attr);

    for(int i = 0;i<100;i++){
        buffer[i] = 'a';
    }


    //create threads
    cout<<"creating threads"<<endl; 
    pthread_create(&p_threadone, &attr, firstthreadfunc, null);
    pthread_create(&p_threadtwo, &attr, secondthreadfunc, null);
    pthread_create(&p_threadthree, &attr, thirdthreadfunc, null);


    //terminate threads
    pthread_join(p_threadone,null);
    pthread_join(p_threadtwo,null);
    pthread_join(p_threadthree,null);



    return 0;




}

感谢 WhozCraig 和 Tony,您的回答解决了问题。我明白我做错了什么。

【问题讨论】:

  • 请修正您的代码缩进。谢谢!
  • 很抱歉。让我知道这是否更好。
  • 1) 你为什么期望 secondThreadFunc 在 thirdThreadFunc 之前运行,因为它们使用相同的条件变量? 2)条件变量可以自发地发出信号——你应该有一个循环来检查条件,然后再继续
  • 托尼,感谢您的评论。好的,这很有意义。如何在循环中检查 pthread_cond_t 变量的变化?对不起,如果这是一个愚蠢的问题,我只是在学习这个。

标签: c++ pthreads


【解决方案1】:

首先,你被困在哪里。 thread2 或 thread3 中的以下行是症结所在:

pthread_cond_wait(&buffer_cond, &buffer_mutex);

现在你在问,“为什么?”因为您将条件变量误认为是状态;不是信号机制。条件变量旨在用于向感兴趣的服务员发出其他状态变化的信号:谓词。你没有。考虑以下修改后的代码版本。

这使用两个谓词值(我建议您坚持每个 condvar 一个,直到您对它们更熟悉;开始简单),用相同的互斥体保护它们并用相同的条件变量指示它们的变化。需要注意的重要一点是,在我们知道我们等待的谓词尚未准备好之前,我们不会等待条件变量。由于我们锁定了互斥体,我们可以安全地检查该谓词:

#include <iostream>
#include <string>
#include <unistd.h>
#include <pthread.h>
using namespace std;

const int NUM_THREADS = 3;

char buffer[100];
bool bDataReady = false;
bool bDataWaiting = false;

pthread_mutex_t buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t buffer_cond = PTHREAD_COND_INITIALIZER;


void* firstThreadFunc(void* proc)
{
    string a = "Data Received";

    pthread_mutex_lock(&buffer_mutex);
    cout<<"ThreadOne"<<endl;
    std::copy(a.begin(), a.end(), buffer);
    buffer[a.size()] = 0;
    cout << buffer << endl;

    bDataReady = true;
    pthread_cond_broadcast(&buffer_cond);
    pthread_mutex_unlock(&buffer_mutex);
    return NULL;
}

void* secondThreadFunc(void* proc)
{
    string a = "Data Processed";

    pthread_mutex_lock(&buffer_mutex);
    while (!bDataReady)
        pthread_cond_wait(&buffer_cond, &buffer_mutex);

    cout<<"ThreadTwo"<<endl;
    std::copy(a.begin(), a.end(), buffer);
    buffer[a.size()] = 0;
    cout << buffer << endl;

    bDataReady = false;
    bDataWaiting = true;
    pthread_cond_broadcast(&buffer_cond);
    pthread_mutex_unlock(&buffer_mutex);
    return NULL;
}

void* thirdThreadFunc(void* proc) 
{
    string a = "Data Sent";
    pthread_mutex_lock(&buffer_mutex);

    while (!bDataWaiting)
        pthread_cond_wait(&buffer_cond, &buffer_mutex);

    cout<<"Thread Three"<<endl;
    std::copy(a.begin(), a.end(), buffer);
    buffer[a.size()] = 0;
    cout << buffer << endl;

    bDataWaiting = false;
    pthread_cond_broadcast(&buffer_cond);
    pthread_mutex_unlock(&buffer_mutex);
    return NULL;
}


int main() {

    pthread_t  p_threadOne, p_threadTwo, p_threadThree;;

    pthread_attr_t attr;
    pthread_attr_init(&attr);

    for(int i = 0;i<100;i++){
        buffer[i] = 'a';
    }


    //create Threads
    cout<<"creating threads"<<endl;
    pthread_create(&p_threadOne, &attr, firstThreadFunc, NULL);
    pthread_create(&p_threadTwo, &attr, secondThreadFunc, NULL);
    pthread_create(&p_threadThree, &attr, thirdThreadFunc, NULL);


    //terminate Threads
    pthread_join(p_threadOne,NULL);
    pthread_join(p_threadTwo,NULL);
    pthread_join(p_threadThree,NULL);

    return 0;
}

输出

creating threads
ThreadOne
Data Received
ThreadTwo
Data Processed
Thread Three
Data Sent

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-13
    • 2011-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多