Информационный сайт

 

Реклама
bulletinsite.net -> Книги на сайте -> Программисту -> Троелсен Э. -> "С# и платформа .NET. Библиотека программиста" -> 130

С# и платформа .NET. Библиотека программиста - Троелсен Э.

Троелсен Э. С# и платформа .NET. Библиотека программиста — СПб.: Питер, 2004. — 796 c.
ISBN 5-318-00750-3
Скачать (прямая ссылка): cplatforma2004.pdf
Предыдущая << 1 .. 124 125 126 127 128 129 < 130 > 131 132 133 134 135 136 .. 320 >> Следующая

Это несложно проиллюстрировать на примере. Правда, для простоты в нашем случае мы при помощи двух потоков будем портить вывод данных не в файл, а на системную консоль, но принципиально это ничего не меняет. Мы создадим новое многопоточное консольное приложение С# с именем MuLtiThreadSharedData. В этом приложении будет использован класс WorkerCl ass, практически такой же, как и в предыдущем примере:
Internal class WorkerC 'ass t
public void DoSomewdrkO
{
Il Выполняем привычную работу
fortlrit 1-0: І < 5: І++)
{
Console.WrlteLine( "Worker says: {0}.". i):
}
}
}
В приложении такжебудет еще один класс — MainClass. В этом варианте 1? іnCJass будет создавать три отдельных дополнительных потока. Каждый из этих потоков будет совместно использовать один и тот же объект класса WorkerCl ass:
public class MainClass {
public static int Main(string[] args) {
Il Создаем единственный объект класса WorkerClass WorkerClass w = new WorkerClass();
I/ Создаем три отдельных потока, каждый из которых производит вызов //к одноиу и тону же объекту
thread workerThreadA = new ThreadCnew ThreadStart(w.DoSomeWork)); "Thread workerThreadB - new ThreadCnew ThreadStart(w.DoSomeWork)); Thread workerThreadC = new ThreadCnew ThreadStart(w.DoSameWork));
II Теперь запускаем все три потока WorkerThreadA. Start О; WorkerThreadB. StartO; WorkerThreadC.Starte):
return 0:
}
]
Перед тем как запустить это приложение, давайте разберемся в существе проблемы. Первичный поток домена приложения запускает три дополнительных потока. Все три потока совместно используют одни и те же данные — единственный объект класса WorkerClass. Поскольку мы не используем никакой блокировки ресурсов, скорее всего, вывод на системную консоль будет испорчен: один процесс
Именованные потоки 311
начинает вывод на консоль, в его вывод вклинивается другой, их обоих отт^стг" третий и т. д. Результат непредсказуем. Три разных варианта того, что может получиться в результате работы этого приложения, представлены на рис. 6.44-6.46.
< ¦ D:\CSharpBook\labs\Chapter 6\Multi
1)<.г(мч- says uiirker :;.<у:;-. 0,
JSl ж]
¦llorker says І,
llorker says 2,
Worker says Worker says: llorker says: 0,
Marker says 0,
Worker says I.
Worker says 1,
Worker says 2,
Worker says 2,
Worker says 3,
Worker says 3,
Worker says 4,
Worker says 4,
llorker says 3,
Worker says 4.
Press any key to continue
UL
M
Рис. 6.44. Вывод данных испорчен: потоки мешают друг другу
Ua гke v s ays Worker says •.<">•! • I says llorker says Uorker says llorker says Worker says Worker says Worker says Worker says Worker says llorker says llorfcer says llorker says Worker says
2І 3, 4,
Uorker says: 0.
I...........
1, 2, 3, 4,
Press any key to continue
LIE
T
Рис. 6.45. Ложалуй, так еще хуже. Соперничество потоков приводит к непредсказуемым результатам
Г n:\CShtirpBook\Labs\C
orker says: Worker Worker says - 1, Worker says: 2 ,
llorker says Worker says llorker says Worker says Worker says Worker says Worker says Worker says Worker says Worker says Worker says Worker says
3, 4,
Worker 1, 2, 3,
Worker
1.
2,
3,
4; ...
;ays : 0,
any key Io COIltill
UL
Рис. 6.46. Возможен и такой вариант. Вывод все равно испорчен
312 Глава 6 - Сборки, потоки и домены приложений
Для решения подобных проблем в С# предусмотрены средства программной синхронизации доступа к общим данных. Их мы и рассмотрим в следующих разделах.
Ключевое слово lock
Первый способ синхронизации доступа к методу DoSemeWe^kf) объекта NorkerCl ass — воспользоваться ключевым словом leck. Это ключевое слово позволяет заблокировать блок кода таким образом, что в каждый отдельный момент времени его сможет использовать только один поток. Всем остальным потокам придется ждать, пока поток, занявший этот блок кода, закончит свою работу. Применение ключевого слова производится очень просто:
internal class WorkerClass
I
public void аоьо;пЫогкО {
Il Только один поток в конкретный ноиент времени сможет выполнять этот
// код!
lock(this)
і
Il Делаем все ту же работу forCint і-0; і < 5: і++) t
Console.WriteLine("Worker says: {0}.". і);
і
Если мы запустим наш пример с измененным классом Worker~С1 ass, мы увидим, что теперь вывод на консоль производится исключительно аккуратно (рис. 6.47).
D:\LShdipUaok\Labs\Lha
'Worker И,
Uorker says 1,
Worker says 2,
Uorke • says 3,
Uorke» sayc 4,
Uorke • says 0,
Uorke - says 1^
Uorke * says 2 ,
Uorke ¦ says 3 ,
Worker says 4,
Uorke • says 0,
Uorke* says 1,
Uorke * says 2,
UorkeP says 3,
Uorke ь cays 4, Press any key to continue
Рис. 6.47. Между потоками царит гармония
Можно считать, что ключевое слово lock в С# — аналог примитива CR IT ICAL-SECTIUN и соответствующих вызовов АРІ в традиционных приложениях Win32.
Код приложения MultiThreadSharedData можно найти в подкаталоге Chapter 6..
Применение System Threading, Interlocked 313
Использование System.Threading. Monitor
Ключевое слово lock в С# — это всего лишь сокращение для синтаксической конструкции с применением класса System.Threading. Monitor, Такая синтаксическая конструкция, заменяющая 1 оск, в нашем случае могла бы выглядеть следующим образом:
Предыдущая << 1 .. 124 125 126 127 128 129 < 130 > 131 132 133 134 135 136 .. 320 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100