Многопоточность в .NET (Multithreading) Часть 2. Пример

Army of 12 Monkeys

Далее представлен практический пример синхронизации потоков. Работа с потоками описана в первой части заметки посвященной многопоточности

Пример приведенный ниже демонстрирует ситуацию нарушения целостности данных при отсутствии синхронизации потоков в обращении к общим данным. Закомментировав строки синхронизации потоков (с оператором lock), можно увидеть как потоки начнуть "грязно ругаться" в консоль:)

Вот исходник примера. Сам проект прикреплен к заметке. Некоторые разъяснения в комментах в коде.

Содержимое файла Main.cs:

using System;
using System.Threading;

namespace ThreadTest2
{
    // Программа иллюстрирует синхронизацию и работу с потоками.
    // Потоки выводят на экран текстовую информацию параллельно.
    // Потоки используют общие "данные", доступ к которым синхронизирован.
    // Ожидают завершения друг друга.
    // Работа потоков прекращается поочередно после нажатия "Enter"

    class MainClass
    {
        // для хранения переменной отдельный класс, так как она является передаваемой по значению,
        // хотя возможно можно было просто запаковать (это пришло в голову лишь при написании этих строчек)
        class MyData
        {
            // один из потоков меняет значение переменной на true,
            // а второй на false, по прошествии таймаута проверяют сохранность значения.
            public bool boo = false;
        }
        // функция первого потока
        static void func1(object param)
        {
            MyData data = param as MyData;
            while(true)
            {
                // задержка чтобы поток не захватил ресурс полностью
                Thread.Sleep(1000);
                lock(data)
                {
                    data.boo = true;
                    // задержка для проверки разрыва
                    Thread.Sleep(100);
                    if(!data.boo)
                    {
                        Console.WriteLine("thread-1 : incomplete transaction");
                    }
                    else
                    {
                        Console.WriteLine("thread-1 : complete");
                    }
                }
            }
        }
        // функция второго потока
        static void func2(object param)
        {
            MyData data = param as MyData;
            while(true)
            {
                Thread.Sleep(100);
                lock(data)
                {
                    //Console.WriteLine("thread-2 : here");
                    data.boo = false;
                    Thread.Sleep(100);
                    if(data.boo)
                    {
                        Console.WriteLine("thread-2 : incomplete transaction");
                    }
                    else
                    {
                        Console.WriteLine("thread-2 : complete");
                    }
                }
            }
        }
        
        public static void Main(string[] args)
        {
            MyData data = new MyData();
            Thread thread1 = new Thread( new ParameterizedThreadStart(func1));
            Thread thread2 = new Thread( new ParameterizedThreadStart(func2));
            Thread.Sleep(100);
            thread1.Start(data);
            thread2.Start(data);
            Console.ReadLine();
            thread1.Abort();
            thread2.Abort();
        }
    }
}

Прикрепленный файлРазмер
ThreadTest2.zip7.61 кб
вернуться назад