Прежде всего: я полностью новичок в мьютексе/многопоточном программировании, поэтому извините за любую ошибку заранее...
У меня есть программа, которая запускает несколько потоков. Нити (обычно один за ядро cpu) делают много вычисления и "мышления", а затем иногда они решают позвонить конкретный (общий) метод, который обновляет некоторые статистические данные. concurrency для обновлений статистики управляется с помощью мьютекса:
stats_mutex.lock();
common_area->update_thread_stats( ... );
stats_mutex.unlock();
Теперь к проблеме. Из всех этих потоков есть один конкретный поток, который требует почти приоритет в реальном времени, потому что это единственный поток, который фактически работает.
С "почти приоритетом в реальном времени" я имею в виду:
Предположим, что поток t0 является "привилегированным", а t1.... t15 - нормальным Что происходит сейчас:
- Поток t1 получает блокировку.
- Потоки t2, t3, t0 вызовите метод lock() и дождитесь его успешного завершения.
- Тема t1 вызывает unlock()
- Один (случайно, насколько я знаю) потоки t2, t3, t0 успешно приобретает блокировка и другие продолжают ждать.
Что мне нужно:
- Thread t1 получает блокировку.
- Потоки t2, t3, t0 вызовите метод lock() и дождитесь его успешного завершения.
- Тема t1 вызывает unlock()
- Тема t0 получает блокировку, поскольку она привилегирована
Итак, какой лучший (возможно, самый простой) способ сделать это?
То, что я думал, это иметь переменную bool, называемую "Privileged_needs_lock".
Но я думаю, мне нужен другой мьютекс, чтобы управлять доступом к этой переменной... Я не знайте, правильно ли это...
Дополнительная информация:
- мои потоки используют С++ 11 (с gcc 4.6.3)
- код должен запускаться как на Linux, так и на Windows (но тестируется только на Linux в данный момент).
- Производительность по механизму блокировки не является проблемой (моя проблема с производительностью связана с вычислениями внутреннего потока, а число потоков всегда будет низким, один или два на процессорное ядро максимум)
Любая идея ценится. Благодаря
Ниже работает решение (три пути mutex):
#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 = С++ 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;
}