2016-04-08 2 views
-1

В этой программе на C++ я создал 10 потоков, которые участвуют друг в друге, чтобы получить критический раздел. Для этого я использую условную переменную, как указано ниже. Диспетчер в этой программе предоставит один поток за раз, чтобы войти в критический раздел. Но есть тонкая проблема. когда диспетчер предоставит нить для ввода, он установит переменную ready_pipe true. Если на этот раз приходит новый поток (до того, как пользователь установит ready_pipe = flase), поток новичка будет проходить через критический раздел без разрешения., обеспечивающий критический раздел для потоков в C++

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

using namespace std; 

std::condition_variable con_var_pipe; 
bool ready_pipe = false; 
std::mutex pipe_mutex; 

bool critical_section_is_free=true; 

void dispatcher() 
{ 

    while(true) 
    { 

     if(critical_section_is_free) 
     { 
      critical_section_is_free=false; 

      // send signal to a thread to enter critical section 
      std::lock_guard<std::mutex> lk(pipe_mutex); 
      ready_pipe = true; 
      con_var_pipe.notify_one(); 

     } 
    } 
} 


void consumer() 
    { 
    std::unique_lock<std::mutex> lk(pipe_mutex); 

    /* The Problem is Here at below line.When a new thread comes, 
     it will pass through this block because it see ready_pipe is true!!!*/ 

    con_var_pipe.wait(lk, [] {return ready_pipe;}); 

    /// critical section starts 
    ready_pipe=false; 
    /// here accessing pipe is occurring . 

    /// critical section ends 
    critical_section_is_free=true; 


} 

int main() 
    { 
    std::thread allThreads[10]; 

    for(int i = 0 ; i<10 ; i++) 
    { 
     allThreads[i]=std::thread(consumer); 
    } 

    thread disp(dispatcher); 

    for(int i = 0 ; i< 6 ; i++) 
    { 
     allThreads[i].join(); 
    } 

    disp.join(); 

    return 0; 
} 

Кроме того, этот код также недостаточен из-за действия (true) в диспетчерской функции и делает ожидание.

Так вопросы:

1-как создать взаимное исключение, когда приходит новый поток.

2-как избежать занятости в диспетчере().

3-и как потоки подаются в порядке их поступления и регистрации в режиме ожидания().

+0

Существует на самом деле не вопрос, там где-нибудь. Какой у вас вопрос о внесении изменений, которые вы обсуждаете? Как я могу вам помочь? –

+0

@DavidSchwartz Сэр, когда новый поток достигает ожидания(), он может пройти через критический раздел, если see ready_pipe == true. но только один поток должен проходить через время (который диспетчер предоставил и установил для него ready_pipe = true). –

+0

Справа. Так в чем ваш вопрос? Вам нужен алгоритм? Если да, попросите его. Вам нужна реализация? Если это так, опишите алгоритм, который вам нужен. Невозможно сказать, какую помощь вам нужно. –

ответ

1

Просто используйте два счетчика и логические для реализации базовой схемы «возьмите номер».

Один счетчик, released_thread, указывает, какая нить может продолжаться. Это логически эквивалентно индикатору «теперь обслуживающий».

Другой, next_waiter, указывает, какой поток ждет следующего. Это логически эквивалентно следующему числу, которое будет принято

Булев указывает, разрешен ли поток и когда он закончен, поэтому исполнительный знает, когда нужно позвонить по следующему номеру.

алгоритмы заключаются в следующем:

Ждать:

  1. Приобретать замок.

  2. Обратите внимание на значение переменной next_waiter и увеличивайте его.

  3. Передача (уведомлять все) переменную условия.

  4. Подождите от переменной состояния до тех пор, пока логическое значение истинно и released_thread счетчика равно значению записанный на шаге 2.

  5. Release замок.

  6. По завершении приобретите замок, установите значение boolean на false, передайте переменную условия и отпустите блокировку.

Исполнительный:

  1. Приобретать замок.

  2. Ожидание переменной условия до тех пор, пока значение boolean не будет установлено, и next_waiter не равно released_thread.

  3. Increment released_thread и установить значение boolean в true.

  4. Трансляция переменной условия.

  5. Перейти к шагу 2.

+0

Спасибо, сэр. Это именно то, чего я хочу. использование двух целых чисел - очень хороший подход. –

+0

Возможно, вы предпочтете использовать две переменные условия, одну для выпуска официанта и одну, чтобы уведомить исполнительную компанию о завершении задачи. Не забудьте передать переменную состояния официанта (уведомить все). –

+0

да, конечно. Большое спасибо. Я знаю, что сообщество Stack гордится вами, сэр. ;) –

Смежные вопросы