Г. Шилдт - С#4.0 Полное руководство (1160795), страница 169
Текст из файла (страница 169)
Пример передачи аргумента методу патока. чя1ЬЧ Буясет; чялпо Буясет.ТЬгеабьпри с1аяя МуТЬгеаб ( рчЫ1с Тпс Сопля( рпЫТс ТЬгеаб ТЬгс); УУ Обратите внимание на то, что конструктору класса О МуТЬгеаб передается такие значение типа Тпю роЫ1с МуТЬгеаб(ясг1ЬЧ пате, Тпс пот) ( Соппт = О( О Вызвать конструктор типа РагатетегагебТЬгеабзсагс О явньяч образом только ради наглядности примера.
ТЬгб = пен ТЬгеаб(ГЫя.поп); ТЬгб.нате = пате; Здесь переменная пот передается методу Бсагс() О в качестве аргумента. тьгб.Бгагг(пот)( О Обратите внимание на то, что в этой форме метода Поп() О указывается параметр типа оЬБесю нога Воп(обзеся ппт) ( Сопяо1е.игьгеььпе(ТЬгб.нате + " начат со счета " + пот) бо ( ТЬгеаб.Я1еер(500); Сопяо1е.нгвсешпе("В потоке " + ТЬгб.нате + ", Соопс = " + Соопс)( Сопля++; ) нЬгте (Соппт.
< (1пс) пшп); Сопяо1е.нгебешпе (ТЬгб.мате + " завершен."); ) с1аяя Раяялгчоето ( ясасьс чогб Матп() ( 846 Часть П. Библиотека С() О Обратите внимание на то, что число повторений передается этим двум объектам типа Мутьгеаб. Мутагеаб шт = пен Мутьгеаб("Потомок $1", 5); МуТЬгеаб шг2 = пен Мутьгеаб("Потомок $2", 3); бо ( Тптеаб.51еер(100); ) нШ1е (шг.тпгб.1як11че ) шг2.тпгб.1як11че); Сопяо1е.иг1тешпе("Сановной поток завершен.") Ниже приведен результат выполнения данной программы, хотя у вас он может оказаться несколько иным. Потомок$1 начат со счета 5 Потомок $2 начат со счета 3 В потоке Потомок 42, Сопят = 0 В потоке Потомок $1, Соппг = 0 В потоке Потомок $1, Сонат = 1 В потоке Потомок $2, Сопла = 1 В потоке Потомак $2, Сопля = 2 Потомок $2 завершен.
В потоке Потомок $1, Соопг = 2 В потоке Потомок $1, Сопла = 3 В потоке Потомок $1, Сопла = 4 Потомок 41 завершен. Основной поток завершен. Как следует из приведенного выше результата, первый поток повторяется пять раз, а второй — три раза. Число повторений указывается в конструкторе класса МуТЛгеаб и затем передается методу Впп (), служащему в качестве точки входа в поток, с помощью параметризированной формы РагашесегьвебтьгеабБсагс метода Бсагс () . Свойство 18Вас1щгояпб Как упоминалось выше, в среде .)ч)ЕТ Ргагпе)чог)4 определены две разновидности потоков: приоритетный и фоновый. Единственное отличие между ними заключается в том, что процесс не завершится до тех пор, пока не окончится приоритетный поток, тогда как фоновые потоки завершаются автоматически по окончании всех приоритетных потоков. По умолчанию создаваемый поток становится приоритетным.
Но его можно сделать фоновым, используя свойство 1янасксгоппб, определенное в классе Тпгеаб, следующим образом. рньгтс Ьоо1 1яваскчгоопб ( Чеш яеш ) Для того чтобы сделать поток фоновым, достаточно присвоить логическое значение С гпе свойству 1 В Вас)опгоппб. А логическое значение Та 1 яе указывает на то, что поток является приоритетным.
Глава 23. Многопоточное программирование. Часть первая: основы 847 Приоритеты потоков У каждого потока имеется свой приоритет, который отчасти определяет, насколько часто поток получает доступ к ЦП. Вообще говоря, низкоприоритетные потоки получают доступ к ЦП реже, чем высокоприоритетные. Таким образом, в течение заданного промежутка времени низкоприоритетному потоку будет доступно меньше времени ЦП, чем высокоприоритетному. Как и следовало ожидать, время ЦП, получаемое потоком, оказывает определяющее влияние на характер его выполнения и взаимодействия с другими потоками, исполняемыми в настоящий момент в системе.
Следует иметь в виду, что, помимо приоритета, на частоту доступа потока к ЦП оказывают влияние и другие факторы. Так, если высокоприоритетный поток ожидает доступа к некоторому ресурсу, например для ввода с клавиатуры, он блокируется, а вместо него выполняетсл низкоприоритетный поток. В подобной ситуации низкоприоритетный поток может получать доступ к ЦП чаще, чем высокоприоритетный поток в течение определенного периода времени. И наконец, конкретное планирование задач на уровне операционной системы также оказывает влияние на время ЦП, выделяемое длл потока. Когда порожденный поток начинает выполняться, он получает приоритет, устанавливаемый по умолчанию.
Приоритет потока можно изменить с помощью свойства Рг1ог1еу, лвляющегося членом класса ТЬгеас(. Ниже приведена общая форма данного свойства: риЫгс тьгеапвг1огггу Ргзог11у( Чегг зег; ) где Т)згеабРту о г1Г у обозначает перечисление, в котором определяются приведенные ниже значения приоритетов. ТпгеаНРгтог1гу.н1оьезг Тпгеапгггог1гу.льочепоппа1 ТпгеаПРг1ог1Су.погва1 ТвгеаНРг1ог11у.ве1очпогва1 ТнгеаПРг1ог11у.ьочезг По умолчанию для потока устанавливается значение приоритета Т)з ге аг(Рг1о гтг у.
Ыогыа1. Для того чтобы стало понлтнее влияние приоритетов на исполнение потоков, обратимся к примеру, в котором выполнлютсл два потока: один с более высоким приоритетом. Оба потока создаются в качестве экземпляров объектов класса Иут)згеас). В методе нип () организуется цикл, в котором подсчитывается определенное число повторений. Цикл завершается, когда подсчет достигает величины 1000000000 или когда статическая переменная асор получает логическое значение с гэе. Первоначально переменнал зеор получает логическое значение Та1зе. В первом потоке, где производится подсчет до 1000000000, устанавливается логическое значение сгце переменной асор.
В силу этого второй поток оканчивается на следующем своем интервале времени. На каждом шаге цикла строка в переменной спггепс)(ате проверяется на наличие имени исполняемого потока. Если имена потоков не совпадают, это означает, что произошло переключение исполняемых задач. Валкий раз, когда происходит переключение задач, имя нового потока отображается и присваиваетсл переменной спггепс)лаве.
Это дает возможность отследить частоту доступа потока к ЦП. По окончании обоих потоков отображается число повторений цикла в каждом из них. 848 Часть П. Бибаиотама Сй Продемонстрировать влияние приоритетов потоков. пя1по Нуягев( овьпя Нувоев.тьгеаб1п9( с1аяя МуТЬгеаб ( рпьтгс гпс Соппс; роь11с тЬгеаб ТЬгб( ясас1с Ьоо1 асор = та1яе( яса11с ясгбпд соггепсиавес /* Сконструировать новый поток. Обратите внимание на то, что данный конструктор еще не начинает выполнение потоков.
*/ рпЬ1гс Мутьгеаб(ягг1пд паве) ( Сопля = 0; тЬгб = пен ТЬгеаб(сита.дпп)) ТЬгб.Маше = паве; соггепсмаве = паве( ) Начать выполнение нового потока. нога Рцп() ( Сопяо1е.иггсеьгпе("Поток " + ТЬгб.Маше + " начат."); с)о ( Соппп+ьс 11(спггепсиаве != ТЬгб.Маше) ( соггепгиаве = ТЬгб.иаве( Сопяо1е.нгтсеьгпе("В потоке " + сиггепоиаве)) ) . ) нь11е(ягор == та1яе аь сопля < 1000000000)( ягор = сгпе( Сопяо1е.иггпеьгпе("Поток " + ТЬгб.Мазе + " завершен."); ) ) с1аяв Рг1ог1суОево ( ясасгс нотс( Маго() ( МуТЬгеаб во1 = пен МуТЬгеаб("с высоким приоритетом"); МуТЬгеаб вс2 = пен МУТЬгеаб("с низким приоритетом"); /2 Установить приоритеты для потоков.
вг1.ТЬгб.Рг1ог1пу = ТЬгеабРг1ог1оу.АЬонеиогва1с вс2.ТЬгб.рг1ог1гу = ТЬгеабрггоггсу.Ве1ониовпа1( О Начать потоки. пот.тогб.Всего И; вг2.ТЬгб.сдагс()( вс1.ТЬгб.до1п()( вс2.ТЬгб.бо1п()( Сопяо1е.иг1сеь1пе()( Сопяо1е.иггсеьгпе("Поток " + вс1.ТЬгб.Маше Глава 28. Многопоточное программнрованнв. Часть первая: основы 848 досчитал до " з шс1.сочпс)) Сопзо1е.иттге01пе )"Поток " + шг2.тптг).паше + " досчитал до " + шс2.Соппс)) Вот к какому результату может привести выполнение этой программы. Поток с высоким приоритетом начат. В потоке с высоким приоритетом Поток с низким приоритетом начат.
В потоке с низким приоритетом В потоке с высоким приоритетом В потоке с низким приоритетом В потоке с высоким приоритетом В потоке с низким приоритетом В потоке с высоким приоритетом В потоке с низким приоритетом В потоке с высоким приоритетом В потоке с низким приоритетом В потоке с высоким приоритетом Поток с высоким приоритетом завершен. Поток с низким приоритетом завершен. Поток с высоким приоритетом досчитал до 1000000000 Поток с низким приоритетом досчитал до 23996334 Судя по результату, высокоприоритетный поток получил около 98% всего времени, которое было выделено для выполнения этой программы.
Разумеется, конкретный результат может отличаться в зависимости от быстродействия ЦП и числа других задач, решаемых в системе, а также от используемой версии гчшс)озчв. Многопоточный код может вести себя по-разному в различных средах, поэтому никогда не следует полагаться на результаты его выполнения только в одной среде. Так, было бы ошибкой полагать, что низкоприоритетный поток из приведенного выше примера будет всегда выполняться лишь в течение небольшого периода времени до тех пор, пока не завершится высокоприоритетный поток. В другой среде высокоприоритетный поток может, например, завершиться еще до того, как низкоприоритетный поток выполнится хотя бы один раз.
Синхронизация Когда используется несколько потоков, то иногда приходится координировать действия двух или более потоков. Процесс достижения такой координации называется синхронизапиеи. Самой распространенной причиной применения синхронизации служит необходимость разделять среди двух или более потоков общий ресурс, который может быть одновременно доступен только одному потоку. Например, когда в одном потоке выполняется запись информации в файл, второму потоку должно быть запрещено делать это в тот же самый момент времени. Синхронизация требуется и в том случае, если один поток ожидает событие, вызываемое другим потоком.
В подобной ситуации требуются какие-то средства, позволяющие приостановить один из потоков до тех пор, пока не произойдет событие в другом потоке. После этого ожидающий поток может возобновить свое выполнение. 850 Часть (1. Библиотека С№ В основу синхронизации положено понятие блокировки, посредством которой организуется управление доступом к кодовому блоку в объекте. Когда объект заблокирован одним потоком, остальные потоки не могут получить доступ к заблокированному кодовому блоку.
Когда же блокировка снимается одним потоком, объект становится доступным для использования в другом потоке. Средство блокировки встроено в язык СФ. Благодаря этому все объекты могут быть синхронизированы. Синхронизация организуется с помощью клк)чевого слова 1ос)с. Она была предусмотрена в С№ с самого начала, и поэтому пользоваться ею намного проще, чем кажется на первый взгляд.