Недавно был на интервью в одной компании и "застрял" на вопросе про RTOS. После недели поисков ответ так и не был найден..
Условие задачи такое: есть 5 потоков, каждый из них увеличивает в цикле общую переменную count на 1. После завершения работы этих потоков, значение count выводится на экран.
Код
unsigned int count = 0;
void thread(void)
{
unsigned int i;
for(i = 0; i < 5; i++)
{
count++;
}
}
void main(void)
{
thread_create(thread, 5); // Создаём 5 экземпляров потока thread и запускаем их
thread_join(); // Ждём пока все 5 потоков завершатся
printf("%u", count); // Выводим значение count на экран
}
void thread(void)
{
unsigned int i;
for(i = 0; i < 5; i++)
{
count++;
}
}
void main(void)
{
thread_create(thread, 5); // Создаём 5 экземпляров потока thread и запускаем их
thread_join(); // Ждём пока все 5 потоков завершатся
printf("%u", count); // Выводим значение count на экран
}
Внимание вопрос: почему программа печатает 2??
Договорились с интервьювером, что операция count++ состоит из 3х ассемблерных команд:
Код
LDR reg, count
ADD reg, #1
STR reg, count
ADD reg, #1
STR reg, count
Т.к. переменная count не защищена ни мьютексом, ни критической секцией, самый пессимистичный вариант, который я "раскрутил" выглядит так:
Код
// начало работы thread1
LDR reg, count // count = 0, thread1.reg = 0
ADD reg, #1 // thread1.reg = 1
// thread1 вытеснен планировщиком, начало работы thread2
LDR reg, count // count = 0, thread2.reg = 0
ADD reg, #1 // thread2.reg = 1
STR reg, count // count = 1
// thread2 завершил работу, управление возвращается к thread1
STR reg, count // count = 1
LDR reg, count // count = 0, thread1.reg = 0
ADD reg, #1 // thread1.reg = 1
// thread1 вытеснен планировщиком, начало работы thread2
LDR reg, count // count = 0, thread2.reg = 0
ADD reg, #1 // thread2.reg = 1
STR reg, count // count = 1
// thread2 завершил работу, управление возвращается к thread1
STR reg, count // count = 1
т.е. в результате один поток делает override результата второго потока и count = 1 после выполнения всех потоков (а не 5, как было бы с мьютексом).
Но: хоть один из потоков все равно увеличит count на 1 в этой схеме, т.е. в результате работы программы count будет не меньше, чем 5.
Как же получается 2? (со слов интервьювера, он наблюдал такой эффект в реальном железе). Подсказка от интервьювера: результат не зависит ни от количества потоков, ни от количества итераций в цикле for