线程同步(笔记)

时间:2020-04-28
本文章向大家介绍线程同步(笔记),主要包括线程同步(笔记)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

两种情况:用户模式和内核模式

一 用户模式

相当于运行自己写的程序,在里面设置线程同步

有volatile和interlocked两者方式

1 volatile

static bool  _stop;
public static void Run()
        {//主线程
            Task.Run(() =>
            {//任务线程
                int number = 1;
                while (!Volatile.Read(ref _stop)) //读取_stop
                {
                    number++;
                }
                Console.WriteLine($"increase stopped,value = {number}");
            });

            Thread.Sleep(1000);
            _stop = true; //更新_stop
}

2 interlocked

private static void DoIncrease(int incrementPerThread)
        {
            int number1 = 0;
            int number2 = 0;

            Console.WriteLine($"use two threads to increase zero. each thread increase {incrementPerThread}.");

            IList<Task> increaseTasks = new List<Task>();

            increaseTasks.Add(Task.Run(() =>
            {
                Console.WriteLine($"thread #{Thread.CurrentThread.ManagedThreadId} increasing number1.");
                for (int i = 0; i < incrementPerThread; i++)
                {
                    Interlocked.Increment(ref number1);
                }
            }));
            increaseTasks.Add(Task.Run(() =>
            {
                Console.WriteLine($"thread #{Thread.CurrentThread.ManagedThreadId} increasing number1.");
                for (int i = 0; i < incrementPerThread; i++)
                {
                    Interlocked.Increment(ref number1);
                }
            }));
            increaseTasks.Add(Task.Run(() =>
            {
                Console.WriteLine($"thread #{Thread.CurrentThread.ManagedThreadId} increasing number2.");
                for (int i = 0; i < incrementPerThread; i++)
                {
                    number2++;
                }
            }));
            increaseTasks.Add(Task.Run(() =>
            {
                Console.WriteLine($"thread #{Thread.CurrentThread.ManagedThreadId} increasing number2.");
                for (int i = 0; i < incrementPerThread; i++)
                {
                    number2++;
                }
            }));

            Task.WaitAll(increaseTasks.ToArray());

            Console.WriteLine($"use interlocked: number1 result = {number1}");
            Console.WriteLine($"normal increase: number2 result = {number2}");
        }

二 内核模式

有事件、信号量和互斥量这三种方式

1 事件 AutoResetEvent

private static void DoIncrease(int incrementPerThread)
{
    int number = 0;
    Console.WriteLine($"use two threads to increase zero. each thread increase {incrementPerThread}.");

    AutoResetEvent are = new AutoResetEvent(true);//初始化一个终止状态的线程同步事件

    IList<Task> increaseTasks = new List<Task>();
    increaseTasks.Add(Task.Run(() =>
    {
        Console.WriteLine($"thread #{Thread.CurrentThread.ManagedThreadId} is increasing the number.");
        for (int i = 0; i < incrementPerThread; i++)
        {
            are.WaitOne();// 阻塞线程,直到被同步事件唤醒
            number++;
            are.Set();// 将事件设为终止状态,唤醒其他线程
        }
    }));
    increaseTasks.Add(Task.Run(() =>
    {
        Console.WriteLine($"thread #{Thread.CurrentThread.ManagedThreadId} is increasing the number.");
        for (int i = 0; i < incrementPerThread; i++)
        {
            are.WaitOne();
            number++;
            are.Set();
        }
    }));

    Task.WaitAll(increaseTasks.ToArray());
    are.Dispose();
    Console.WriteLine($"use AutoResetEvent: result = {number}");
}
View Code

2 信号量 Semaphore

private static void DoIncrease(int incrementPerThread)
{
    int number = 0;
    Console.WriteLine($"use two threads to increase zero. each thread increase {incrementPerThread}.");

    Semaphore semaphore = new Semaphore(1,1); //初始化信号量,这里初始值要设置为1,否则同步会有问题

    IList<Task> increaseTasks = new List<Task>();
    increaseTasks.Add(Task.Run(() =>
    {
        Console.WriteLine($"thread #{Thread.CurrentThread.ManagedThreadId} is increasing the number.");
        for (int i = 0; i < incrementPerThread; i++)
        {
            semaphore.WaitOne();
            number++;
            semaphore.Release(1);// 退出信号量

        }
    }));
    increaseTasks.Add(Task.Run(() =>
    {
        Console.WriteLine($"thread #{Thread.CurrentThread.ManagedThreadId} is increasing the number.");
        for (int i = 0; i < incrementPerThread; i++)
        {
            semaphore.WaitOne();
            number++;
            semaphore.Release(1);

        }
    }));

    Task.WaitAll(increaseTasks.ToArray());
    semaphore.Dispose();
    Console.WriteLine($"use Semaphore: result = {number}");
}
View Code

3 互斥量 Mutex

bool createNew;
using (new Mutex(true, Assembly.GetExecutingAssembly().FullName, out createNew))
{
    if (!createNew)
    {//系统已经存在同名的互斥体,说明已有程序实例在运行
        //这里做一些提示
        Environment.Exit(0);//退出
    }
    else
    {
        //启动实例的代码
    }
}
View Code

三 混合模式

1 Lock

2 ReaderWriterLockSlim

private static readonly ReaderWriterLockSlim _rwlock = new ReaderWriterLockSlim();
public static void DoWork()
{
_rwlock.EnterWriteLock();
//DoWork
_rwlock.ExitWriteLock();
}
View Code

原文地址:https://www.cnblogs.com/wwz-wwz/p/12794781.html