首页 > 编程语言 >《Effective C#》系列之(六)——提高多线程的性能

《Effective C#》系列之(六)——提高多线程的性能

时间:2023-04-28 12:56:08浏览次数:36  
标签:count Effective Thread C# 线程 new static 多线程 public

一、综述
《Effective C#》中提高多线程性能的方法主要有以下几点:

  1. 避免锁竞争:锁的使用会导致线程阻塞,从而影响程序的性能。为了避免锁竞争,可以采用无锁编程技术,如CAS(Compare-And-Swap),Interlocked 等。

  2. 使用 Thread Pool:Thread Pool 是 .NET Framework 提供的一个线程池,它可以管理线程的创建与销毁,并且可以重复利用线程,从而提高程序的性能。建议使用 ThreadPool 来代替手动创建和销毁线程。

  3. 使用 Task Parallel Library(TPL):TPL 是 .NET Framework 提供的一种并行计算库,它可以自动管理线程的创建和销毁,并且可以智能地分配任务给线程池中的线程,从而提高程序的性能。

  4. 减少线程切换:线程上下文切换是非常耗费资源的操作,因此应该尽量减少线程切换的次数。可以通过减少线程睡眠时间、避免过度的 I/O 操作等方式来减少线程切换。

  5. 优化内存分配:在多线程程序中,频繁的内存分配和回收会导致垃圾回收器的频繁触发,从而造成性能瓶颈。可以采用对象池、缓存等方式来优化内存分配。

  6. 使用 Concurrent 集合:Concurrent 集合是 .NET Framework 提供的线程安全的集合类,它可以避免锁竞争和死锁等问题,从而提高程序的性能。

  7. 采用异步编程:异步编程可以避免线程阻塞,从而提高程序的性能。可以使用 async/await 关键字或者 Task 类来实现异步编程。

总之,《Effective C#》中提高多线程性能的方法主要是通过避免锁竞争、使用 Thread Pool 和 TPL 等技术来提高程序的效率。
二、提高多线程性能之避免锁竞争

1、避免锁竞争的具体技术要点
《Effective C#》中避免锁竞争的具体技术主要有以下几点:

  1. 无锁编程:无锁编程是一种基于原子操作和 CAS(Compare-And-Swap)等技术实现线程同步的方式,可以避免锁竞争和死锁等问题。下面是一个使用 Interlocked 类实现无锁计数器的示例代码:
public class Counter
{
    private int count;

    public void Increment()
    {
        Interlocked.Increment(ref count);
    }

    public void Decrement()
    {
        Interlocked.Decrement(ref count);
    }
}
  1. ReaderWriterLock:ReaderWriterLock 是一种读写锁,它可以让多个线程同时读取共享资源,但只允许一个线程写入共享资源。这样可以有效地避免锁竞争和提高程序的性能。下面是一个使用 ReaderWriterLock 实现线程同步的示例代码:
public class Resource
{
    private readonly ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
    private int value;

    public int ReadValue()
    {
        rwLock.EnterReadLock();
        try
        {
            return value;
        }
        finally
        {
            rwLock.ExitReadLock();
        }
    }

    public void WriteValue(int newValue)
    {
        rwLock.EnterWriteLock();
        try
        {
            value = newValue;
        }
        finally
        {
            rwLock.ExitWriteLock();
        }
    }
}
  1. Immutable 对象:Immutable 对象是指不可变的对象,它们的属性值在创建之后不会发生改变。由于 Immutable 对象是线程安全的,可以避免锁竞争和死锁等问题。下面是一个使用 Immutable 对象实现线程同步的示例代码:
public class Person
{
    public string Name { get; }
    public int Age { get; }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

public class ImmutableResource
{
    private readonly Immutable<Person> person;

    public ImmutableResource(Person person)
    {
        this.person = Immutable.Create(person);
    }

    public Person GetPerson()
    {
        return person.Value;
    }

    public ImmutableResource UpdatePerson(Person newPerson)
    {
        return new ImmutableResource(newPerson);
    }
}

总之,《Effective C#》中避免锁竞争的具体技术主要是通过无锁编程、ReaderWriterLock 和 Immutable 对象等方式来实现线程同步,从而提高程序的性能。

附录:多线程基础
多线程编程的技术要点包括线程的创建、同步、互斥、死锁等方面。

  1. 线程的创建
    在C#中,可以通过Thread类来创建一个新线程。例如:
using System;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        Thread newThread = new Thread(DoWork);
        newThread.Start();
    }

    static void DoWork()
    {
        Console.WriteLine("New thread started!");
    }
}

在这个例子中,我们创建了一个新的线程并启动了它,该线程会执行DoWork方法。

  1. 线程的同步
    当多个线程同时访问共享资源时,就需要进行线程同步。C#提供了多种同步机制,如锁、信号量、事件等。例如:
using System;
using System.Threading;

class Program
{
    static int count = 0;
    static object lockObj = new object();

    static void Main(string[] args)
    {
        Thread t1 = new Thread(Increment);
        Thread t2 = new Thread(Increment);

        t1.Start();
        t2.Start();

        t1.Join();
        t2.Join();

        Console.WriteLine("Count: " + count);
    }

    static void Increment()
    {
        for (int i = 0; i < 100000; i++)
        {
            lock (lockObj)
            {
                count++;
            }
        }
    }
}

在这个例子中,我们创建了两个线程来并发地增加count变量的值。为了避免竞争条件,我们使用了lock关键字来锁定共享资源,确保每个线程在修改count变量时都能够独占它。

  1. 线程的互斥
    线程互斥是指多个线程之间相互排斥,只有一个线程能够访问共享资源。在C#中,可以使用Mutex类来实现线程互斥。例如:
using System;
using System.Threading;

class Program
{
    static int count = 0;
    static Mutex mutex = new Mutex();

    static void Main(string[] args)
    {
        Thread t1 = new Thread(Increment);
        Thread t2 = new Thread(Increment);

        t1.Start();
        t2.Start();

        t1.Join();
        t2.Join();

        Console.WriteLine("Count: " + count);
    }

    static void Increment()
    {
        for (int i = 0; i < 100000; i++)
        {
            mutex.WaitOne();
            count++;
            mutex.ReleaseMutex();
        }
    }
}

在这个例子中,我们使用Mutex类来实现线程互斥。在Increment方法中,我们首先调用WaitOne方法来请求锁定Mutex对象,然后修改count变量的值,最后调用ReleaseMutex方法来释放锁定。

  1. 线程的死锁
    线程死锁是指两个或多个线程互相等待对方释放锁定的资源,导致程序永远无法继续执行。为了避免线程死锁,需要遵循一些规则:
  • 避免嵌套锁定
  • 避免循环等待
  • 使用超时机制

例如:

using System;
using System.Threading;

class Program
{
    static object lock1 = new object();
    static object lock2 = new object();

    static void Main(string[] args)
    {
        Thread t1 = new Thread(() =>
        {
            lock (lock1)
            {
                Thread.Sleep(1000);
                lock (lock2)
                {
                    Console.WriteLine("Thread 1");
                }
            }
        });

        Thread t2 = new Thread(() =>
        {
            lock (lock2)
            {
                Thread.Sleep(1000);
                lock (lock1)
                {
                    Console.WriteLine("Thread 2");
                }
            }
        });

        t1.Start();
        t2.Start();

        t1.Join();
        t2.Join();
    }
}

在这个例子中,我们创建了两个线程,每个线程都锁定了两个共享资源。如果这两个线程同时运行,它们就会陷入死锁状态,因为每个线程都在等待对方释放锁定的资源。

标签:count,Effective,Thread,C#,线程,new,static,多线程,public
From: https://www.cnblogs.com/DinAction/p/17361804.html

相关文章

  • Vulkan Support Check and Dynamic Loader C++ code sample
    很多时候不想静态依赖VulkanSDK所提供的静态库,因为会遇到一些过早的电脑不支持vulkan,那么就需要使用动态加载vulkan-1.dll(forWindows)或libMoltenVK.dylib(forMacOS)的方式进行判断了。VulkanSDK提供了相关头文件实现可以做到相关功能,仅需要include一下头文件`vulkan/vulkan.hpp......
  • Anaconda简介及CentOS下的安装及使用
    一、Anaconda简介 Anaconda是一个用于科学计算的Python发行版,支持Linux,Mac,Windows系统,提供了包管理与环境管理的功能,可以很方便地解决多版本python并存、切换以及各种第三方包安装问题。Anaconda利用工具/命令conda来进行package和environment的管理,并且已经包含了Python和相......
  • python中global 和 nonlocal 的作用域
    python引用变量的顺序: 当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量。一globalglobal关键字用来在函数或其他局部作用域中使用全局变量。但是如果不修改全局变量也可以不使用global关键字。1gcount=023defglobal_test():4gcount+......
  • CDN加速WordPress触发CORS导致跨域加载失败
    这两天折腾CDN加速来提升自己博客的访问速度,用的阿里云CDN加速方案;使用的时候发现一个问题,部分资源CDN加速失败,原因是触发了CORS,因为CDN加速网址与博客网址不一致引发的跨域请求不成功;从报错中发现Off与Tff字体加载报错:(index):1AccesstoFontat'http://cdn.5yun.org/wp-conte......
  • Ray Tracing: The Rest of Your Life
    3.OneDimensionalMCIntegration蒙特卡洛积分[1]一般表达式如下:这样做的原因是保持期望值,做到无偏差。重要性采样importancesampling:一般采样的概率分布与目标函数的概率分布一致。5.LightScatteringAlbedo当光子打在材料上,会有一定概率被吸收,也可能被反射出去......
  • Nutch介绍及使用(验证)
    1.Nutch介绍Nutch是一个开源的网络爬虫项目,更具体些是一个爬虫软件,可以直接用于抓取网页内容。现在Nutch分为两个版本,1.x和2.x。1.x最新版本为1.7,2.x最新版本为2.2.1。两个版本的主要区别在于底层的存储不同。1.x版本是基于Hadoop架构的,底层存储使用的是HDFS,而2.x通过使用Apac......
  • Halcon XLD 生成提取&测量及特征筛选
    6.1XLD的生成和提取XLD的创建生成圆轮廓gen_circle_contour_xld算子:gen_circle_contour_xld(: ContCircle : Row, Column, Radius, StartPhi, EndPhi, PointOrder, Resolution :)示例:gen_circle_contour_xld(ContCircle1,500,500,150,0,6.28318,'positiv......
  • The principle of uploading files with command line tools All In One
    TheprincipleofuploadingfileswithcommandlinetoolsAllInOne命令行工具文件上传的原理/TheprincipleofcommandlinetoolfileuploaddemospipgitCDNOSS{"name":"xui","version":"1.0.0","main&q......
  • halcon 仿射变换
    一、两点计算:刚体仿射变换1、vector_to_rigid:1)根据两个以上点对计算计算刚性仿射变换矩阵,支持旋转和平移2、vector_angle_to_rigid1)根据点和角度计算刚性仿射变换矩阵,支持旋转和平移 ......
  • 网页截图,html2canvas简单示例
     <divid="box"><p>asd4a5s6fa6s5f1asf</p><imgstyle="width:200px"src="xxxxxx.png"/><buttonstyle="width:100px;height:30px"onclick="prtsc()">pr......