Почему при многопоточном программировании возникает столько проблем?
Теперь, когда вы получили некоторое представление о многопоточном программировании и о потенциальных проблемах, с ним связанных, мы решили, что в конце этой главы будет уместно ответить на вопрос, вынесенный в заголовок подраздела.
Одна из причин заключается в том, что многопотрчность — процесс нелинейный, а мы привыкли к линейной модели программирования. На первых порах трудно привыкнуть к самой мысли о том, что выполнение программы может прерываться случайным образом, а управление будет передаваться другому коду.
Однако существует и другая, более фундаментальная причина: в наши дни программисты слишком редко программируют на ассемблере или хотя бы просматривают дизассемблированные результаты работы компилятора. Иначе им было бы гораздо проще привыкнуть к мысли, что одной команде языка высокого уровня (такого, как VB .NET) могут соответствовать десятки ассемблерных инструкций. Поток может прерываться после любой из этих инструкций, а следовательно — и посреди команды высокого уровня.
Но и это не все: современные компиляторы оптимизируют быстродействие программ, а оборудование компьютера может вмешиваться в процесс управления памятью. Как следствие, компилятор или оборудование может без вашего ведома изменить порядок команд, указанный в исходном тексте программы [ Многие компиляторы оптимизируют циклические операции копирования массивов вида for i=0 to n:b(i)=a(i):ncxt. Компилятор (или даже специализированное устройство управления памятью) может просто создать массив, а потом заполнить его одной операцией копирования вместо многократного копирования отдельных элементов! ].
Надеемся, эти пояснения помогут вам лучше понять, почему многопоточное программирование порождает столько проблем, — или по крайней мере меньше удивляться при виде странного поведения ваших многопоточных программ!