Как дать приоритет привилегированному потоку при блокировке мьютекса?

Во-первых, :я совсем новичок в программировании мьютексов/многопоток, поэтому заранее извините за ошибку...

У меня есть программа, которая запускает несколько потоков. Нити (обычно по одной на ядро процессора )делает много расчет и «мышление», а потом иногда решают вызвать конкретный (общий )метод, обновляющий некоторую статистику. Параллелизм при обновлении статистики управляется с помощью мьютекса :

stats_mutex.lock();
common_area->update_thread_stats(... );
stats_mutex.unlock();

. Теперь к проблеме. Из всех этих потоков есть один конкретный поток, которому требуется почти
приоритет реального времени, потому что это единственный фактически работающий поток.

Под «приоритетом почти в реальном времени» я имею в виду:

Предположим, что поток t0 является «привилегированным», а поток t1....t15 — обычным. те. Что происходит сейчас:

  • Поток t1 получает блокировку.
  • Поток t2, t3, t0 вызывает метод блокировки ()и ждет его успешного завершения.
  • Поток t1 вызывает разблокировку()
  • Одному (наугад, насколько я знаю )из потоков t2, t3, t0 удается получить замок, а остальные продолжают ждать.

Мне нужно:

  • Поток t1 получает блокировку.
  • Поток t2, t3, t0 вызывает метод блокировки ()и ждет его успешного завершения.
  • Поток t1 вызывает разблокировку()
  • Поток t0 получает блокировку, поскольку он является привилегированным

. Итак, каков наилучший (, возможно, самый простой )способ сделать это?

Я думал о том, чтобы иметь логическую переменную с именем «привилегированный _нуждается в блокировке _».

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

Дополнительная информация:

  • мои темы используют C++11 (начиная с gcc 4.6.3)
  • код должен работать как в Linux, так и в Windows (, но на данный момент тестируется только в Linux ).
  • производительность механизма блокировки не является проблемой (моя проблема с производительностью связана с вычислениями внутренних потоков, а количество потоков всегда будет низким, максимум один или два на ядро ​​​​процессора)

Любая идея приветствуется. Спасибо


Приведенное ниже решение работает (с тремя мьютексами):

#include <thread>
#include <iostream>
#include "unistd.h"

std::mutex M;
std::mutex N;
std::mutex L;

void lowpriolock(){
  L.lock();
  N.lock();
  M.lock();
  N.unlock();
}

void lowpriounlock(){
  M.unlock();
  L.unlock();
}

void highpriolock(){
  N.lock();
  M.lock();
  N.unlock();
}

void highpriounlock(){
  M.unlock();
}

void hpt(const char* s){
  using namespace std;
  //cout << "hpt trying to get lock here" << endl;
  highpriolock();
  cout << s << endl;
  sleep(2);
  highpriounlock();
}

void lpt(const char* s){
  using namespace std;
  //cout << "lpt trying to get lock here" << endl;
  lowpriolock();
  cout << s << endl;
  sleep(2);
  lowpriounlock();
}

int main(){
std::thread t0(lpt,"low prio t0 working here");
std::thread t1(lpt,"low prio t1 working here");
std::thread t2(hpt,"high prio t2 working here");
std::thread t3(lpt,"low prio t3 working here");
std::thread t4(lpt,"low prio t4 working here");
std::thread t5(lpt,"low prio t5 working here");
std::thread t6(lpt,"low prio t6 working here");
std::thread t7(lpt,"low prio t7 working here");
//std::cout << "All threads created" << std::endl;
t0.join();
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
t6.join();
t7.join();
return 0;
}

Попробовал приведенное ниже решение, как было предложено, но оно не работает (компилируется с "g++ -std=c++0x -o test test.cpp -lpthread"):

#include <thread>
#include <mutex>

#include "time.h"
#include "pthread.h"

std::mutex l;

void waiter(){
  l.lock();
  printf("Here i am, waiter starts\n");
  sleep(2);
  printf("Here i am, waiter ends\n");
  l.unlock();
}

void privileged(int id){
  usleep(200000);
  l.lock();
  usleep(200000);
  printf("Here i am, privileged (%d)\n",id);
  l.unlock();  
}

void normal(int id){
  usleep(200000);
  l.lock();
  usleep(200000);
  printf("Here i am, normal (%d)\n",id);
  l.unlock();    
}

int main(){
  std::thread tw(waiter);
  std::thread t1(normal,1);
  std::thread t0(privileged,0);
  std::thread t2(normal,2);

  sched_param sch;
  int policy; 

  pthread_getschedparam(t0.native_handle(), &policy, &sch);
  sch.sched_priority = -19;
  pthread_setschedparam(t0.native_handle(), SCHED_FIFO, &sch);

  pthread_getschedparam(t1.native_handle(), &policy, &sch);
  sch.sched_priority = 18;
  pthread_setschedparam(t1.native_handle(), SCHED_FIFO, &sch);

  pthread_getschedparam(t2.native_handle(), &policy, &sch);
  sch.sched_priority = 18;
  pthread_setschedparam(t2.native_handle(), SCHED_FIFO, &sch);

  tw.join();
  t1.join();
  t0.join();
  t2.join();

  return 0;  
}
24
задан d3k 27 July 2012 в 00:06
поделиться