使用sched_yield来控制线程执行

时间:2015-11-02 21:59:12

标签: c++ scheduling

我有2个主题:元音和辅音将重新打印"用户输入语句。元音线程将打印以元音开头的单词,辅音线程将打印以辅音开头的单词...我试图使用sched_yield()以与用户输入相同的顺序输出... 因此,如果用户输入是:嗨所有,辅音线程将打印喜和元音将按顺序打印所有..但似乎我遗漏了一些东西,因为我没有得到相同的顺序..你能帮忙...

void *vowels( void *s )
{
    for(int i = 1; i < noOfTokens; i++){
        string str = tokens[i];
        size_t found = str.find_first_of(vowelList);
        if(found == 0){
            printf("vows %s\n", tokens[i]);
        }
        else {
            sched_yield();
      } 
  }
  pthread_exit(0);
}


/* the cons thread should print all words starting with a consonant.  */
void *consonants( void *s )
{
    for(int j = 1; j < noOfTokens; j++){
        string str = tokens[j];
        size_t found = str.find_first_of(vowelList);
        if(found != 0){
            printf("cons %s\n", tokens[j]);
        }
        else {
            sched_yield();
      } 
  }
  pthread_exit(0);

}

1 个答案:

答案 0 :(得分:1)

正如Kenney所说,仅使用yield无法帮助您同步这两个线程。为此,您必须使用互斥锁或其他同步原语。话虽这么说,我不禁注意到condition variable的帮助可以优雅地解决你的问题。我选择使用c++11std::thread以及std::mutexstd::condition_variable

我简化了你的问题,我的目标是打印偶数和奇数整数按照它们输入的顺序购买两个不同的线程(一个线程负责偶数,另一个负责奇数)。一种可能的解决方案可能是:

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

std::mutex m;
std::condition_variable cv;
unsigned int index = 0;

void ProcessEvenNumbers(void *p_array)
{
    std::vector<int>& buffer(*reinterpret_cast<std::vector<int>*>(p_array));
    std::unique_lock<std::mutex> lock(m);

    while (index < buffer.size())
    {
        if (buffer[index] % 2 == 0)
        {
            std::cout << "thread_1: " << buffer[index] << std::endl;
            ++index;
        }
        else
        {
            cv.wait(lock);
        }
    }
}

void ProcessOddNumbers(void *p_array)
{
    std::vector<int>& buffer(*reinterpret_cast<std::vector<int>*>(p_array));
    std::unique_lock<std::mutex> lock(m);

    while(index < buffer.size())
    {
        if (buffer[index] % 2 != 0)
        {
            std::cout << "thread_2: " << buffer[index] << std::endl;
            ++index;
        }
        else
        {
            lock.unlock();
            cv.notify_one();
            std::this_thread::sleep_for(std::chrono::microseconds(1));
            lock.lock();
        }
    }

    cv.notify_one();
}

int main()
{
    std::vector<int> buffer{ 1, 3, 24, 5, 100, -23, -2, -2, 7, 9, 11, 13, 15, 17, 2, 4, 6, 8, 10, 12, 14 };
    std::thread thread_2(ProcessOddNumbers, &buffer);
    std::thread thread_1(ProcessEvenNumbers, &buffer);

    thread_1.join();
    thread_2.join();

    return 0;
}

处理偶数(ProcessEvenNumbers())的线程在遇到奇数时使用条件变量来阻塞它自己。处理奇数(ProcessOddNumbers())的线程在遇到偶数时使用notify_one()取消阻塞另一个线程,并通过尝试重新锁定互斥锁来阻止自身(此时已经被锁定了其他线程)。

std::this_thread::sleep_for()非常重要,因为它强制进行上下文切换,允许thread_1thread_2发出状态变量信号后锁定互斥锁。

运行线程的

P.S。顺序无关紧要。