- •2. Основные понятия объектно-ориентированного программирования 7
- •3. Управляемый и неуправляемый код и данные 17
- •3.3 Управляемый и неуправляемый код и данные 17
- •5. Классы 38
- •6. Наследование классов и интерфейсы 49
- •7. Программа ввода/вывода информации 62
- •8. Управляемые данные и их использование 76
- •Предисловие
- •2.1 Объекты
- •2.Основные понятия объектно-ориентированного программирования
- •2.2Классы
- •Пример 2.2.2. Создание и использование объектов.
- •2.3Объекты, классы и uml
- •2.4Основные свойства объектно-ориентированного программирования
- •Пример 2.4.1. Класс cColBall, наследуемый класс cBall.
- •Пример 2.4.2. Использование функций объектов.
- •2.5Библиотеки классов
- •3.Управляемый и неуправляемый код и данные
- •3.1Виртуальная машина языка Java
- •3.2Общеязыковая среда выполнения clr платформы .Net
- •3.3Управляемый и неуправляемый код и данные
- •3.4Сборщик мусора
- •3.5Ссылочные типы и типы-значения
- •3.6Метаданные
- •3.7Библиотеки, пакеты и пространства имён
- •4.1О типах данных
- •4.2Консольный ввод и вывод
- •Void main (void)
- •Import java.Io.*;
- •Int X; // Целочисленная переменная X
- •4.3Объявление переменных
- •4.4Операторы динамического распределения памяти new и delete
- •Int X; // Выделить память в стеке
- •Пример 4.4.2. Использование оператора new в языках Java и c#.
- •Import java.Io.*;
- •Int X; // Выделить память в стеке для переменной
- •Int X; // Выделить память в стеке для переменной
- •4.5 Массивы
- •Пример 4.5.2. Описание одномерных массивов на изыках Java и c#.
- •Пример 4.5.4. Создание массивов объектов на языке Java.
- •Import java.Io.*;
- •4.6Объявления структур и перечислений
- •4.7Ссылки
- •Пример 4.7.1. Использование ссылочной переменной.
- •Void main()
- •4.8Перегрузка функций
- •Пример 4.8.1. Перегруженные функции swap (int &, int &) и swap (bool &,bool &).
- •Void swap (int &a, int &b) // Целочисленные параметры
- •Void swap (bool &a, bool &b) // Булевские параметры
- •4.9Объявление функций и передача аргументов по умолчанию
- •Void swap (int &, int &);
- •Void swap (char 8t, char &);
- •Пример 4.9.1. Задание значений параметров функции по умолчанию.
- •Void main ( )
- •5.Классы
- •5.1Определение класса
- •Пример 5.1.1. Описание класса и создание его объектов.
- •Int X; // Закрытая переменная X
- •Void Show ( ) // Открытая функция
- •Int X; // Закрытая (по умолчанию) переменная X
- •Void Show ( ) // Открытая функция
- •Пример 5.2.1. Описание функций вне класса.
- •Int X; //Закрытая переменная х
- •Void Set(int m,char n); // 0бъявление функции Set
- •Void Show (); // Объявление функции Show()
- •5.3Некоторые замечания о классах
- •Пример 5.3.1. Области видимости.
- •Int GetK() {return k;} // Функция GetK() видна в файле, классе а и в
- •Int n; // Переменная n закрыта и видна только в классе а
- •Int GetM () {return n;} // Функция GetM() открыта и видна
- •5.4Объекты в объектах
- •Пример 5.4.1. Объект содержит объект другого класса.
- •Void Show ()
- •Void Show ()
- •5.5Специальный вид функций класса - конструкторы и деструкторы
- •Пример 5.5.1. Перегруженные конструкторы.
- •Int GetX() {return X;} // Возвратить значение закрытой переменной
- •Void ShowX () // Вывести значение переменной
- •5.6Статические функции класса
- •Пример 5.6.1. Статические функции.
- •Void f() {Console::WriteLine("f()");} // Обычная функция
- •Int main() // Главная статическая функция Main()
- •6.Наследование классов и интерфейсы
- •6.1Об интерфейсах
- •Пример 6.2.1. Программа, использующая порождение public.
- •Void Show ()
- •Void Show()
- •Int main() // Главная статическая функция
- •6.4Использование конструктора базового класса
- •Java и j#
- •Java и j#
- •Пример 6.4.1. Выполнение конструкторов.
- •Int X; // Закрытая переменная X
- •Int Get() {return X;} // Получить значение X
- •Int main() // Главная статическая функция main()
- •6.5Сокрытые переменные, функции и их использование
- •Пример 6.5.1. Сокрытые переменные и функции.
- •6.6Интерфейсы
- •Interface class имя-интерф [ : public имя-базов-интерф
- •Interface имя-интерф [ : имя-базов-интерф [, имя-базов-интерф ] ... ]
- •Interface имя-интерф [ extends имя-базов-интерф
- •Interface Ipe // Интерфейс, объявляющий свойство p и функцию Hallo
- •Int p {set; get;} //Объявить свойство
- •Void Hallo(); // Объявить функцию
- •6.6.1Определение интерфейса
- •6.6.2Базовые интерфейсы
- •6.7 Упаковка и распаковка типов данных
- •Int main() // Главная статическая функция main()
- •7.Программа ввода/вывода информации
- •7.1Постановка задачи
- •Диаграмма вариантов использования
- •7.2 Диаграмма классов
- •7.3Диаграмма последовательности
- •7.4Диаграмма видов деятельности
- •Пример 7.5.1. Реализация класса cComputer.
- •Пример 7.5.2. Реализация класса cShop.
- •Пример 7.5.3. Реализация класса cData.
- •Void main()
- •Пример 7.5.4. Реализация Inf-приложения.
- •Void main()
- •7.6Реализация Inf-приложения иа языке c# Пример 7.6.1. Реализация Inf-приложения иа языке c#.
- •Int cost; // Стоимость компьютера
- •Int year; // Год изготовления
- •Inf.Enter();
- •Inf.Enter();
- •Inf.Show();
- •8.Управляемые данные и их использование
- •Void set(тип value)
- •Пример 8.1.2. Свойства в Java.
- •Import java.Io.*;
- •Пример 8.2.1. Создание и использование делегата.
- •Void main() // Главная функция программы
- •Пример 8.2.2. Использование делегата как параметра функции.
- •Void r(void) {Console::WriteLine ("r");}
- •Void main () // Главная функция программы
- •Void имя-функции ( void );
- •Пример 8.3.1. Событие и делегат.
- •Void main ()
- •Vold имя-функции-активизации()
- •Пример 8.3.2. Использование события.
- •Void GenerateEv() // Функция-генератор события
- •Void main()
- •Void GenerateEv (String л str) // Функция- генератор события
- •Void main ( )
- •06BeKTfirst клaccaUseEvпoлyчилcoбытиe one
- •Interface iEv
- •IE,HandlerEv (); // Выполнить обработчик
- •Void GenerateEv ( ) // Сгенерировать событие
- •Void main (void)
- •V{ oid FireConnectEvent (object sender, SourceEventArgs e)
- •Void FireConnectEvent (object sender, EventArgs args)
- •8.4. Уведомления и события в Java
- •8.4.1. Уведомления в Java
- •Void notifyObservers () - уведомить всех обозревателей данного наблюдаемого
- •Void notifyObservers (Object obj) - уведомить всех обозревателей данного на-
- •Void update(Observable observable. Object obj) - эта функция данного объекта
- •Import java.Util.*;
- •II Два наблюдателя и один наблюдаемый объект
- •Importjava.Util.*;
- •Importjava.Utll,*;
- •Importjava.Util.*;
- •Int num; // Номер уведомляющего объекта
- •8.4.2. События в Java
- •Import java.Utii.*;
- •Void DatePerformed (DataDate dd); // Обработчик
- •Int n; // Номер объекта-приёмника
- •Int num; // Номер объекта приёмника
- •Import cJHappenListerner.*;
- •Importjava.Uti).*;
- •Void performedHappen (HappenData hD);
- •Import cJHappenListerner.*; | | Импортировать библиотеку
- •9. Потоки и синхронизация их выполнения
- •9.1. Процессы
- •9.3. Потоки в Java
- •Int num; // Номер потокового объекта
- •2. Поскольку объявленному в классе cThread потоковому объекту thr типа
- •9.4. Потоковый объект, выдающий событие
- •If (lllfe) // Если потоковый объект не функционирует,
- •ImportJava,util.*;
- •If (!life) // Если потоковый объект не функционирует,
- •9.5. Поток получил событие из объекта
- •If (!life)
- •If (received)
- •Importjava.Utll.*;
- •If (lllfe)
- •If (received)
- •9.6. Синхронизация выполнения потоков
- •9.6.1. Операторы lock и synchronized
- •Int num; // Номер объекта
- •9.6.2. Связи между потоками
- •9.6.2.1. Связи меяеду потоками в Java
- •If(waiting)
- •9.6.2.2. Связи между потоками в c#
- •If (I moving)
- •9.6.2.1.1 Наязыке Java, отличаясьтолько применением функций монитора
- •10. Библиотека .Net Framework и библиотеки
- •10.1. Приложение
- •10.2. Классы, объекты и элементы приложения
- •Visual Studio .Net как библиотеки .Net Framework, так и пакетов языка Java
- •10.3. Простейшие приложения
- •Import java.Awt.*;
- •Void main ( )
- •10.3.1.1. Оказывается, класс Form сам наследует множество других классов,
- •10.4. Сообщения Windows, события и делегаты
- •X0.4.1. Обработка событий мыши на языке c#
- •Void OurMouseDown (object sender, MouseEventArgs args);
- •Vold maln ()
- •10.4.3. Обработка событий мыши на языке Java с использо-
- •10.4.4. Связь события с несколькими объектами на языке c#
- •10.5. Ещё раз о событиях и уведомлении в языке Java
- •10.5.1. Обработка событий элементов интерфейса пользовате-
- •ItemListener, KeyListener, MouseListener, MouseMotionListener, TextListener
- •10.5.2. Обработка событий мыши на языке Java, используя
- •Importjava.Awt.Event.*;
- •Importjava.Awt.*;
- •Import java.Awt.Event.*;
- •Importjava.Awt.*;
- •Import java.Awt.Event.*;
- •10.5.3. Обработка событий мыши на языке Java, используя классы адап-
- •Importjava.Awt.*;
- •Importjava.Awt.Event.*;
- •Importjava.Awt.*;
- •Importjava.Awt.Event.*;
- •10.5.4. Обработка событий мыши на языке Java, используя внутренние
- •Import java.Awt.*;
- •Import java.Awt.Event.*;
- •Importjava.Awt.*;
- •Import java.Awt.Event.*;
- •10.5.5. Обработка события закрытия окна
- •Import java.Awt.*;
- •Import java.Awt.Event.*;
- •10.6. Графика
- •10.6.1. Графические объекты
- •15, 15, 60, 70); // Нарисовать эллипс
- •Vold maln ()
- •10.7. Событие Paint и его обработчик
- •Int len; // Текущая длина массива points
- •Void OurMouseDown (object sender, MouseEventArgs arg)
- •Invalidate ( ); // Перерисовать
- •Int len; // Текущая длина массива points
- •Import java.Awt.Event.*;
- •10.8. Управляющие элементы
- •1 «Button j 1
- •Import java.Awt,event.*;
- •Int n; // Индекс цвета
- •10.8.4,10.8.5 И 10.8.6, а также программа, поэтапно разрабатываемая в разде-
- •Invalidate ();
- •Importjava.Awt.*;
- •Import java.Awt.Event.*;
- •Importjava.Util.*;
- •10.9. Дочерние окна
- •Int n; // Индекс массива colors
- •IiTipOrt jav'a.Avvt. •)
- •Import java.Awt.Event.*;
- •Int n; // Индекс цвета
- •Virtual void OnPaint (PaintEventArgs л arg) override // Перерисовать область
- •10.10.3, В котором вызываются две функции.
- •Importjava.Awt.*;
- •Importjava.Awt.Event.*;
- •It); // Подписать обработчик
- •Void main ( )
- •11.1. Программа с точки зрения пользователя
- •11.2. Объектное представление программы
- •11.3. События, потоки и их синхронизация
- •11.4. Поэтапная разработка программы
- •11.4.1. Первый этап. Разработка класса Warehouse
- •4Cxrt()
- •Int partLoad; // Выгружаемая или загружаемая порция
- •If(full) return false; // Полный грузовик не загружать
- •Invalidate ();
- •Importjava.Awt.*;
- •Importjava,utll.*;
- •Void notifyObs (WarehouseEventArgs arg)
- •Int partLoad; // Получаемая или помещаемая порция груза
- •If (full) return false;
- •If(full) return false; // Полный грузовик не загружать
- •Void Change ( )
- •Invalidate ();
- •Importjava.Awt.*;
- •Importjava.Util.*;
- •Import cjWarehouse.*
- •11.4.2. Второй этап. Разработка классов ContrlRegion и Lorry
- •11.4.2.1, А сам класс представлен в примере 11.4.2.1. Класс ContrlRegion язы-
- •Importjava.Awt.Event.*;
- •Void Work ( ) // Выполнить работу
- •Int number;
- •Int number;
- •Int timePeriod;
- •Int y; // Координата y пути грузовика
- •Invalidate ();
- •11.4.3. Третий этап. Разработка приложения csLorryAndWarehouse
- •4IorryAndWa rho uses()
- •4Main()
- •Int y; // Координата y пути грузовика
- •Invalidate ( );
- •If(lorry.GetFull())
- •If(lorry.GetLeftRight()) g.SetColor(Color.Red);
- •Int numLorry; // Номер грузовика
- •Void But_Run (Object Ло, EventArgs ле)
- •Void main ( )
- •11.4.4. Четвертый этап. Удаление ресурса
- •Int number;
- •If(!lorry.Running)lorry.Run ( );
- •12. Зачетные задачи
- •12.1. Задание 1
- •Importjava.Awt.*;
- •Import Java.Awt.Event.*;
- •Importjava.Util.*;
- •12.2. Задание 2
- •Importjava.Awt.*;
- •Importjava.Awt.Event,*;
- •Importjava.Util.*;
- •Invalidate ( );
- •12.3. Задание 3
- •Importjava.Awt.*;
- •Import java.Awt.Event.*;
- •Importjava.Util.*;
- •If(bool) Start ();
- •If(lrunnlng)
- •Void BallFunc ()
- •Void ThrFunc ( )
- •Vold OnButAdd (object obj, EventArgs arg)
- •Void HandlerEv ( )
- •Invalidate ( );
- •12.4. Задание 4
- •If(reg.R.Contains(p) && !inRect)
- •If(!reg.R,Contains(p) && lnRect)
- •Void OnButAdd (object obj, EventArgs arg)
- •Void HandlerEv ( )
- •Invalidate ();
- •Importjava.Awt.*;
- •Importjava.Awt.Event.*;
- •Importjava.Utll.*;
- •Int w, int h, Color c, Wind wind)
- •If(reg.R.Contains(p) && !lnRect)
- •If(!reg.R.Contains(p) && inRect)
- •If(d.GetDel())
- •13. Ещё о важном в объектно-ориентирован-
- •13.1. Виртуальные функции
- •13.1.1. Преобразование типов
- •Void f ( ) {cout « "ca:: f" « endl;}
- •Void main ( )
- •Void f ()
- •Void main ( )
- •Vold f ( )
- •Vold Do (ca* pCa)
- •Void main ( )
- •13.1.2, Виртуальные функции
- •Virtual void f ( ) {Console::WriteLine ("a:: f");}
- •Void f ( ) {Console::WriteLine ("b:: f");}
- •Void f ( ) {Console::WrlteLlne ("c:: f");}
- •Vold f ( ) {Console::WrlteLlne("b:: f");}
- •Vold Do (a* pA)
- •Void main ()
- •13.1.3. Виртуальные функции, используемые в книге
- •13.2. Абстрактные классы и функции
- •13.2.1. Абстрактные функции
- •13.2.2. Абстрактные классы
- •Void f ( ) {Console::WriteLine ("b:: f");}
- •Vold f ( ) {Console::WriteLine ("d:: f");}
- •Vold main ( )
- •13.2. Нововведения в языке c#
- •13.2.1.Делегаты и события
- •Iorry.Run ( );
- •13.3.2. Статические классы
- •Int partLoad; // Выгружаемая или загружаемая порция
- •If(!full)
- •Invalidate ( );
- •Int number;
- •Int y; // Координата y пути грузовика
- •Iorry.Stop ();
- •If(llorry.Running)lorry.Run ( );
- •Invalidate ( );
- •1) Создать новый проект:
- •Value 28, 30
- •Value type 34
- •Visual Studio .Net и Edipse.
- •420111, Казань, Дзержинского, 3. Тел.: 292-24-76.
9.6.1. Операторы lock и synchronized
Операторы synchronized языка __________Java и lock языка C# позволяют пред-
ставить любой оператор программы в виде критической секции, которая свя-
зывается с некоторым объектом и может выполняться только одним пото-
ком среди потоков, имеющих доступ к этому объекту. Выполнение других
потоков, пытающихся воспользоваться этим объектом, приостанавливается,
пока указанный оператор не выполнится, освободив тем самым этот объект
от своего монопольного использования. То есть операторы lock (lock - бло-
кировать) и synchronized (synchronized - синхронизирован) захватывают (бло-
кируют) объект, на который они ссылается, на время выполнения указанного
оператора, и освобождает его, как только оператор выполнится.
Операторы synchronized языка Java и lock языка C# имеют следующую
грамматику:
synchronized (object) оператор // Java
lock (object) оператор // C#
где object - ссылка на объект, который нужно синхронизировать,
оператор - оператор, реализующий критическую секцию.
Ссылаемый объект (разделяемый ресурс) используется одновременно
несколькими потоками. Если этот объект используется некоторым потоком,
то он блокируется от использования другими потоками. Часто в качестве
ссылки на объект применяется ключевое слово this, если предполагается
употребить критическую секцию применительно к объекту, к которому она
принадлежит. Как известно, обращение к статическим данным и функциям
осуществляется через класс, в котором они размещены.
Поскольку обычно к блокируемому объекту применяется не один, а по-
следовательность из нескольких операторов, то в качестве оператора, сле-
дующем за ключевыми словами synchronized и lock, используют составной
оператор, включающий требуемую последовательность операторов в фигур-
ных скобках. Эта последовательность операторов представляет собой крити-
ческую секщно, которая защищена операторами synchronized и lock и являет-
ся единственным владельцем процессора на время своего выполнения с объ-
ектом.
Пример 9.6.1.1. Оператор lock и потоки на языке C#.
///////////////
/ / c #
using System;
using System.Threading;
class Obj // Класс разделяемого объекта
{
private int count= 0; // Счётчик
public int Count // Свойство Count
{
set {count= value;}
get {return count;> >
>
class User // Класс объектов с
{
private Obj obj;
int num;
Thread thr;
потоками
// Ссылка на разделяемый объект
// Номер объекта
// Ссылка на поток
// Конструктор
public User (Obj obj, int num)
{
this.obj= obj;
thls.num= num;
// Создать и стартовать поток
thr= new Thread(new ThreadStart(this.ThrFunc));
thr.Start();
// Потоковая функция
private void ThrFunc ()
{
lock(obJ) // 1
{
while (obJ.Count < 5)
{
//lock(obj) // Блокировать разделяемый объект//2
{
obj.Count= obj.Count +1; // Увеличить счётчик
Thread.Sleep (1); // Поспать
Console.WrlteLine("User" + num + " count= "
+ obj.Count);
} >
Console.WriteLine("Thread of User" + num +
" flnished");
>
>
>
class LockTest // Касс с основным потоком
{
static vold Maln ( )
{
Obj obj= new Obj (); // Создать разделяемый объект
User usl= new User (obj, 1); // Создать первый объект с потоком
User us2= new User (obj, 2); // Создать второй объект с потоком
Console.WriteLine ("OKl"); // Создали объекты
Thread.Sleep (100);
Console.WriteLine ("OK2"); // Завершился основной поток
>
/>*
Result: Вариант А. Оператор lock отсутствует (Строки 1 и 2
закомментированы).
OKl
Userl count= 1
User2 count= 1
Userl count= 3
User2 count= 3
Userl count= 5
Thread of Userl finished
User2 count= 5
Thread of User2 finished
OK2
Result: Вариант Б. Оператор lock внутри цикла while охватывает блок,
включающий увеличение счетчика, функции Sleep и WriteLine
(строка 1 закомментирована, а строка 2 не закомментирована).
OKl
Userl count= 1
User2 count= 2
Userl count= 3
User2 count= 4
Userl count= 5
Thread of Userl finished
User2 count= 6
Thread of User2 finished
OK2
Result: Вариант В. Оператор lock охватывает оператор while
(строка 1 не закомментирована, а строка 2 закомментирована).
OKl
Userl count= 1
Userl count= 2
Userl count= 3
Userl count= 4
Userl count= 5
Thread of Userl finished
Thread of User2 finished
OK2
*/
В примере 9.6.1.1 класс Obj описываеттип объекта, доступ к которому
осуществляется несколькими потоками, которые изменяют значение счётчи-
ка count и считывают это значение. Доступ к счётчику осуществляется по-
средством свойства Count.
Класс User описывает тип объектов, каждый из которых содержит поток,
осуществляющий увеличение счётчика разделяемого объекта класса Obj на 1
и выдачу полученного значения на консоль. Потоковая функция перед выда-
чей на консоль задерживается на 1 мс, подразумевая, что поток мог бы вы-
полнить и другие какие либо операции с разделяемым объектом. В течение
выполнения потоковой функции другие потоки могут изменить значение
счётчика, если доступ к используемому разделяемому объекту не синхрони-
зировать - это будет показано ниже.
Выполнение потоковой функции состоит в пятикратном обращении к разде-
ляемому объекту obj класса Obj. При каждом обращении разделяемый объект
блокируется оператором lock с составным оператором (критической секци-
ей), осуществляющим увеличение счётчика, задержку и выдачу на консоль.
Функция Main() класса LockTest создаёт объект obj класса Obj и объ-
екты usl и us2 класса User, потоки которых используют объект obj.
При создании объектов us 1 и us2 их конструкторы устанавливают но-
мера этим объектам и фиксируют ссылки на разделяемый объект obj. Затем
создаются и запускаются их потоки.
Рассмотрим несколько вариантов выполнения этой программы.
Вариант А. Созданы два объекта usl и us2 с потоками. Синхронизация па-
раллельного выполнения потоков отсутствует, оператор lock не использует-
ся. Обращение к разделяемому объекту obj класса Obj не управляется, по-
этому результат изменения счётчика не предсказуем. Он может быть как в
примере 9.6.1.1, но может и отличаться в зависимости от производительности
процессора.
Вариант Б. Созданы два объекта usl и us2 с потоками и их потоки запуще-
ны. Оператор lock охватывает нутро цикла while, позволяя только одному по-
току менять значение счётчика count разделяемого объекта obj. Результат ра-
боты программы показывает, что, действительно, объект obj разделяется ме-
жду потоками. При изменении значения счетчика count некоторым потоком,
этот поток захватывает объект obj, не позволяя другому потоку также изме-
ПОТ1 ?uaupuTjp pujirouva pnnnt lA'1 nMuntTwrg mfifm., nT,nrnci***jr4 лиггцл итл . u . . u w . . w . W 1 1 I .W V . w . Ц . и и V W U . . . > . ^ J j^ ~ ' J J " 1 " * " . " ^uvu.ut u^wi ^wuuiAM U ( ^ i l v , i . W
значение счетчика count последовательно меняется потоком каждого объекта
класса User, поскольку после обращения к разделяемому объекту с использо-
ванием оператора lock поток выходит из оператора lock, позволив другому
потоку на один цикл его потоковой функции захватить разделяемый объект.
Итак, не мешая друг другу, потоки раздельно используют разделяемый
объект obj, увеличивая последовательно значение его счётчика на 1. Благо-
даря оператору lock поток каждого объекта захватывает разделяемый объ-
ект, исключив доступ к нему со стороны другого потока
Вариант В. Созданы два объекта usl и us2 с потоками и их потоки запуще-
ны. Оператор lock теперь охватывает оператор while, позволяя только одному
потоку изменять значение счётчика count разделяемого объекта obj до завер-
шения циклов while. Результат работы программы показывает, что, действи-
тельно, объект obj захватывается одним потоком.
По результату работы варианта В возникает вопрос: почему же после
завершения потока объекта usl не появились строки, указывающие о выпол-
нении циклов извлечённого из очереди ожидающих потоков потока объекта
us2? Почему появилась строка 'Thread of User2 finished"? Дело в том, что за-
вершившийся поток объекта usl увеличил значение счетчика до 5, поэтому
цикл while потока объекта us2 не выполнялся, и посему сразу появилось со-
общение об его завершении. Стоит вставить в конце потоковой функции опе-
ратор
obj.setCount (0);
и ситуация изменится, поток объекта us2 оживёт.
Использование оператора synchronized языка Java, аналогичное приме-
нению lock в языке C#, приведено в примере 9.6.1.2.
Пример 9.6.1.2. Оператор synchronized и потоки на языке Java.
///////////////
// Java и J#
class Obj // Класс разделяемого объекта
{
private lnt count= 0; // Счётчик
/p/u bСlвicо йvсoтidв о sCeotuCnotu nt(lnt Count) {count= Count;>
public int getCount ( ) <roturn count;>
}
class User extends Thread // Класс объектов с потоками
{
private Obj obj; // Ссылка на разделяемый объект
