2015-11-09 5 views
1

У меня такая странная проблема с потоками. На моем Mac с OS X это прекрасно работает, но как только я больше расскажу о своем рабочем столе, на котором работает Ubuntu, я столкнулся с проблемами.Thread Synchronization C++

По сути то, что я делаю следующее:

Function() { 

    for(i = 1 to 10) 
     while(array not completely changed) { 
     pthread_mutex_lock(&lock); 
     -- perform actions 
     pthread_mutex_unlock(&unlock); 
     } 
    } 
} 

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

Thread 1 grabs lock 
performs opperations on array 
Thread 1 releases lock 
Thread 2 grabs lock 
performs calculations on array 
Thread 2 releases lock 

и так далее в спину и вперед образец до тех пор, пока массив не были завершены изменены, но в Linux все из расчета резьбы 1 завершена, а затем Начинается тема 2.

Так что я получаю:

Thread 1 grabs lock 
performs opperations on array 
Thread 1 releases lock 
Thread 1 grabs lock 
performs calculations on array 
Thread 1 releases lock 
Thread 1 grabs lock 
performs calculations on array 
Thread 1 releases lock 

И так далее, пока массив не будет полностью изменен, как только я приращение для цикла, то поток 2 будет выполнять все расчеты и продолжить эту картину.

Может ли кто-нибудь объяснить, что происходит?

+0

Это планировщик потоков, что вы заинтересованы в. Проверьте это http://man7.org/linux/man-pages/man7/sched.7.html. Начиная с версии 3.14, Linux предоставляет политику планирования сроков (SCHED_DEADLINE). Вероятно, вы заинтересованы в круговой политике. – alvits

+2

Обратите внимание: у нас есть класс 'std :: thread' в текущем стандарте C++, который должен использоваться предпочтительно над API-интерфейсом библиотеки pthreads'. –

+0

Если вы хотите принудительно переключиться на определенный поток, вам нужно управлять этим самостоятельно, иначе совершенно случайно, какой поток получит блокировку (это не тот порядок, по которому они доходят до блокировки). –

ответ

4

Вы испытываете «голод». Добавьте небольшой вызов nanosleep, чтобы дать другим потокам возможность запускать. Добавьте вызов вне пары мьютексов (например, после разблокировки). Тема 1 - монополизация вещей.

Вы можете также рассмотреть вопрос о реструктуризации и расщеплению до критической [требует блокировки] против некритического работы:

while (more) { 
    lock ... 
     do critical stuff ... 
    unlock ... 
    nanosleep ... 
    do non-critical stuff 
} 
+0

Где я могу поместить этот «нанослое» в свой код? – QQCompi

+0

После того, как замок был выпущен, но до его получения. Включение первого потока в режим сна позволит время для второго потока получить блокировку и т. Д. – Tas

+0

Работал как шарм, спасибо большое! – QQCompi