• Learn Orleans 03


    https://github.com/wswind/learn-orleans/tree/master/01.HelloWorld
    上一章,我们通过Orleans完成了一个最简单的HelloWorld样例。实现了面向对象风格的RPC调用。

    本章,我来讲解Actor的无锁机制。

    源码下载地址:https://github.com/wswind/learn-orleans

    首先我们来看一个经典的多线程例子

    class Program
    {
        static int count = 0;
        static void Main(string[] args)
        {
            var tasks = new List<Task>();
            for (int i = 0; i < 100; i++)
            {
                var task = Task.Run(() => count++);
                tasks.Add(task);
            }
            Task.WaitAll(tasks.ToArray());
            Console.WriteLine(count);
        }
    }
    

    我们建立了100个线程来执行count++,但是由于没有使用对象锁,程序并发执行会导致最终结果不正确:

    >dotnet run
    86
    

    要处理这个问题也很简单,那就是使用线程锁:

    static void Main(string[] args)
    {
        object locker = new object();
        var tasks = new List<Task>();
        for (int i = 0; i < 100; i++)
        {
            var task = Task.Run(() => {
                lock(locker)
                {
                    count++;
                }
    
            });
            tasks.Add(task);
        }
        Task.WaitAll(tasks.ToArray());
        Console.WriteLine(count);
    }
    

    首先由于资源发生了竞争,线程锁会影响多线程的运行效率。
    其次,在分布式系统中,不同服务运行在不同机器的不同进程中,想锁就没那么容易了,需要通过其他更为复杂的架构锁(如Redis)来处理。

    而Orleans面对这类问题,它是不用锁的。如我们在第一章中所说,Actor有一个邮箱,它会依次执行消息。因此我们可以理解Actor是单线程地在依次执行任务,因此也就不存在资源竞争问题。
    为了实现这种Actor机制,Orleans其实在运行时中,封装了底层处理。开发者无需关心底层细节,只需要记住,Interface接口要求需要统一返回Task或泛型的Task<>。

    我们修改上一章的代码,添加两个接口,来模拟上面的例子看在Orleans中会如何。

    Task AddCount();
    Task<int> GetCount();
    

    并在Grain中实现

    private int _count;
    public Task AddCount()
    {
        _count++;
        return Task.CompletedTask;
    }
    
    public Task<int> GetCount()
    {
        return Task.FromResult(_count);
    }
    

    在client调用时,通过多线程调用

    var tasks = new List<Task>();
    for(int i=0;i<100;i++)
    {
        var task = Task.Run(() => friend.AddCount());
        tasks.Add(task);
    }
    Task.WaitAll(tasks.ToArray());
    
    Console.WriteLine(await friend.GetCount());
    

    可以得到返回结果仍旧是100 。

    无锁就没有资源竞争,对于分布式系统中的重要性是不言而喻的。

  • 相关阅读:
    网络通信过程
    路由表转发分析实例
    随机生成MAC地址和IP地址
    zabbix监控LAMP全教程
    linux ssh利用公钥免密登陆
    如果Mysql插入字符始终乱码怎么办?
    Windows 桌面利用 Navicat等工具连接 虚拟机Mysql
    pagefile.sys 虚拟内存
    linux常用命令---------------find
    当你使用Pycharm编译程序的时候,遇到了这个问题,该怎么办?please select a valid interpreter
  • 原文地址:https://www.cnblogs.com/wswind/p/12563354.html
Copyright © 2020-2023  润新知