Когда хочется в программе иметь нескольких потоков, возниает проблема их синхронизации. Многие говорят, что синхронизация - это дело программиста. Но ее реализация делает программу менее сопровождаемой и хуже читаемой. Какие возникают проблемы при добавлении кода? Если мы обращаемся к уже существующей переменной, то обязательно надо проверить - есть ли для нее синхронизация, и если нет, то придется добавить ее. Примеров много, но общее одно - синхронизацию должен добавлять сам программист, отчего и возникают ошибки. Нет ни одного языка программирования, предназначенного специально для параллельности. А надо бы. Предлагаю так: *** Главная вещь - поток выполнения *** Все новые переменные и структуры - общие и некому не принадлежат. Также и с функциями. Так мы как-будто создаем сам исполняемый модуль, без потоков. Переменные можно создавать внешние (вне кода) и внутренние (внутри кода). Code (Text): //Внешние перемнные const int a1 = 12; // переменная попадает в секцию только для чтения unsigned int b1; // попадает в секцию для чтения / записи abc var { // внутренние int b1; char d1 = 35; }; {{ ... // Содержимое кода }} Внутренние переменные могут вызываться только из кода, в к-м их объявили (abc). Если код хочет обратиться к внешней переменной с таким же именем, надо: Code (Text): extern::b1 Каждому потоку принадлежат функции и переменные, созданные в программе. *** Использование кода *** Каждый код делается в виде inline-функции. Чтобы использовать код, надо записать его в теле потока: Code (Text): Thread1 begin abc // это код, названный abc end. Там, где в потоке указывается код (abc), используется синхронизация. Перед выполнением код - вход в критич. секцию этого кода, а после выполнения кода - выход из критической секции. Так синхронизируются все внутренние переменные, лишая возможности 2 потока одновременно писать и читать. *** Внешние переменные *** Перед чтением / записью во внешнюю переменную используется ее Семафор. Если создать внешнию структуру, то будет один семафор на всю структуру, а не по одному на каждую переменную. Все используемые кодом внешние переменные записываются в раздел global: Code (Text): global { a1, b2; } Заметьте, что критические секции, семафоры и события использует сам язык программирования, а не код программы. Сама программа их использовать не может - нужно пользоваться средствами языка. Если код используется только одним потоком, критич. секции в нем отменяются. То же самое с внешними переменными и семафорами. Можно самому использовать эти принципы самому, кодя программу на Си, но тогда придется самому всегда обращаться в семафорам и крит. секциям. Но данные вещи лучше реализовать с помощью препроцессора Си, а не писать новый язык. Возможно, вместо препроцессора, а Си++ добавится еще одна идеалогия, с новыми ключевыми словами. P.S. Это все мне просто пришло в голову, но сейчас я занят кое-чем, поэтому тему буду посещать редко.
AndreyMust19 как это нет?? и потоки и блокировки и каналы и средства для работы со всем этим добром, все там есть.
Ну почему же... например ActiveOberon, который плотно связан с операционкой А2. Приведу цитату из Вики: http://ru.wikipedia.org/wiki/Bluebottle_OS Встроенная процедура AWAIT используется для синхронизации активности с состоянием системы. Аргументом AWAIT может быть только логическое условие; активность сможет продолжить свое выполнение только после того, как условие станет истинным. Пока условие не выполняется, активность остается приостановленной (suspended); если это происходит внутри защищенного блока, то блокировка снимается на время приостановки активности (что позволяет другим активностям изменять состояние объекта и сделать условие истинным); активность возобновляет работу только если она сможет снова захватить блокировку. Более подробно можно почитать в сообщении о язык (рус.) http://maxandreev.narod.ru/oberon/ActiveOberonReport_RUS.html PS: там также есть ссылки на другие решения
Что это за бред. Одно ядро - один поток. И языки тут не причём. Если я на VBA напишу код и запущу у себя(аффинитет 2), то он параллельно на двух процессорах выполняться будет.
Ада, ActiveOberon... ну и кто на них программирует, поднимите руки? Эти языки обладают лишь средствами синхронизации, но программист все равно их должен сам использовать. Не один язык не делает это сам, позволяя человеку забыть о синхронизации. К тому же это языки, в которые всего накидали, как в Си++, а потом думают - как же нам что-то добавить в язык, чтобы это можно было заюзать в любой парадигме. Интересно - наверняка люди, когда пишут программы с несколькими потоками (на Си, Паскале), придерживаются каких-то правил/идеалогий, чтобы в этих программах потом проще было с потоками разобраться. Может на этот счет даже целая методика есть, поделитесь опытом. Вон, в ядре Linux (и других, наверняка, тоже) сколько ошибок посадили, а все из-за того, что один программист ставит в одном месте семафор, а другой программист ничего не знает об этом и никаких семафоров не проверяет. Если была бы хоть какая-то поддержка языка, таких проблем синхронизации между 2-мя программистами не было. Clerk Может слово Thread или нить вам больше подойдет.
Синхронизация между программистами это сильно звучит. Компилятор будет везде совать синхронизацию? А производительность пострадать не может?
А производительность пострадать не может? не может, а будет страдать. Но, как уже сказано - если к переменной обращается только один блок кода, эта переменная не синхронизируется семафором. Если блок кода используется только в одном потоке, то он не помещается в критическую секцию. Константы синхронизируются только для чтения. Собственно, язык во время компиляции синхронизирует только то, что надо синхронизировать. Вы, наверное, подумаете, что это сложно, но это часть языка, - некоторые компиляторы, ведь, все равно лезут со своей оптимизацией, если их не просят, например, встраивают ф-ю, если она вызывается только один раз или strcpy для Ascii заменяют на inline цикл копирования байтов.
Зачем синхронизировать константы? ^) Даже если происходит запись/чтение то синхронизация далеко не всегда нужна. Я лично пока не видел, чтобы на компилятор полностью перекладывали эти проблемы и правильно делают. Синхронизация это как правило переход в ядро и потеря тысяч тактов. Даже в C# сделали ручную синхронизацию и её поддержку в некоторых контейнерах, но никак не авто. А С++ вообще ориентирован на максимальную производительность, и там это тем более сомнительно.
AndreyMust19 Больше подходит задача. Для начала следует поставьть вопрос - под какую ось нужна среда, в оси где есть окна параллельно ничего выполнять вы не сможите. Всегда будут прерывания.
Clerk Я вас не понимаю, скажите по-русски или сходите на балкон - проветритесь. Речь идет о языке, к-ый сам будет следить за синхронизацией, вместо программиста. Booster Ну да, только с чтением синхронизировать не надо. P.S. Опять убегаете от темы.
AndreyMust19 Я вас тоже не понимаю, что подразумевается под синхронизацией и чего ? 1. Обращений к какимто переменным - ну так на шине сигнал залочивания есть, если он есть другие ядра будут простаивать. Тоесть выполнили вы атомарно обращение к памяти - вас будут ждать, остальные ядра отстанут от текущего, да и выравнивание имеет значение и есчо много чего. Железо не позволяет параллельно чтото исполнять. 2. Любое прерывание/исключение приведёт к переключению задачи(понимать буквально). Виндоз, линукс и тп. не пригодно для параллельно исполнения задач, програмное обеспечение не поддерживает это, ибо не поддерживает процессор. 3. Зачем это нужно ? Обычно следующие инструкции требуют результат исполнения предыдущих, собственно что и является главным ограничением в производительности. Если вам под винду нужно синхронно обращаться к переменной - используйте спин-блокировки с запрещёнными прерываниями.
Clerk, это не ядро, а уровень приложения и его потоки. А смысл в том, чтобы перед обращениями к переменным на запись / чтение, язык автоматом вставлял обращение к семафору. А при работе фрагмента кода, принадлежащего неск. потокам, происходит вход / выход в критическую секцию. Речь идет не о ядре, а о программировании.