三分钟掌握共享内存 & Actor并发模型

点击上方蓝字进行关注

吃点好的,很有必要。今天介绍常见的两种并发模型:共享内存&Actor

共享内存

面向对象编程中,万物都是对象,数据+行为=对象;

多核时代,可并行多个线程,但是受限于资源对象,线程之间存在对共享内存的抢占/等待,实质是多线程调用对象的行为方法,这涉及#线程安全#线程同步#。

假如现在有一个任务,找100000以内的素数的个数,如果用共享内存的方法,代码如下:

可以看到,这些线程共享了sum变量,对sumsum++操作时必须上锁。

using System;
using System.Threading.Tasks;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Diagnostics;

namespace Paralleler
{
    class Program
    {
        static object syncObj = new object();
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            ShareMemory();
            sw.Stop();
            Console.WriteLine($"共享内存并发模型耗时:{sw.Elapsed}");
        }

        static void ShareMemory()
        {
            var sum = 0;
            Parallel.For(1, 100000 + 1,(x, state) =>
            {
                var f = true;
                if (x == 1)
                    f = false;
                for (int i = 2; i <= x / 2; i++)
                {
                    if (x % i == 0)  // 被[2,x/2]任一数字整除,就不是质数
                        f = false;
                }
                if(f== true)
                {
                    lock(syncObj)
                    {
                        sum++;   // 共享了sum对象,“++”就是调用sum对象的成员方法
                    }
                }
            });
            Console.WriteLine($"1-100000内质数的个数是{sum}");
        }
    }
}
共享内存更贴合"面向对象开发者的固定思维", 强调线程对于资源的掌控力。

Actor模型

Actor模型则认为一切皆是Actorshare nothig, Actor模型内部的状态由自己的行为维护,外部线程不能直接调对象的行为,必须通过消息才能激发行为,也就是消息传递机制来代替共享内存模型对成员方法的调用, 这样保证Actor内部数据只能被自己修改,

Actor模型= 数据+行为+消息。

还是找到100000内的素数,我们使用.NET TPL Dataflow来完成,代码如下:

每个Actor的产出物就是流转到下一个Actor的消息。

using System;
using System.Threading.Tasks;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks.Dataflow;
using System.Diagnostics;

namespace Paralleler
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            Actor();
            sw.Stop();
            Console.WriteLine($"Actor并发模型耗时:{sw.Elapsed}");  
        }

        static void Actor()
        {
            var linkOptions = new DataflowLinkOptions { PropagateCompletion = true };
            var transfromBlock = new TransformBlock<int,bool>(x=> 
            {
                var f = true;
                if (x == 1)
                    f = false;
                for (int i = 2; i <= x / 2; i++)
                {
                    if (x % i == 0)  // 被[2,x/2]任一数字整除,就不是质数
                        f = false;
                }
                return f;
            }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism =50 });
           
            var sum = 0;
            var actionBlock = new ActionBlock<bool>(x=>
            {
                if (x == true)
                    sum++;
            },new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 50 });
            transfromBlock.LinkTo(actionBlock, linkOptions);
            // 准备从pipeline头部开始投递
            for (int i = 1; i <= 100000; i++)
            {
                transfromBlock.Post(i);
            }
            transfromBlock.Complete();  // 通知头部,不再投递了; 会将信息传递到下游。
            actionBlock.Completion.Wait();  // 等待尾部执行完成
            Console.WriteLine($"1-100000内质数的个数是{sum}");
        }
    }
}
Actor并发模型强调的是消息触发。

还不过瘾

共享内存模型:其实是并行线程调用对象的成员方法,这里不可避免存在加锁/解锁, 需要开发者自行关注线程同步、线程安全。

调试多线程的都懂.gif

Actor模型:以流水线管道的形式,各Actor独立处理各自专属业务,等待消息流入。

我也很容易推断,每个Actor的伪代码实现:存在循环,不断处理新流入的消息。

 var queue= new Queue(1000); 
 for{
    if(queue.Dequeue() != null) {
       // Done bussiness 
    }
    Thread.Sleep(50ms);
 }

所以Actor模型,开发者不用关注线程锁,同时,Actor模型解耦了调用关系,天然适合分布式场景。

总结陈词

1.何为“并发模型”,模型是达成某个方案的编程风格,共享内存/Actor并发模型说不上孰优孰劣,适用场景有偏向。2.共享内存并发模型,更强调多线程对于资源的掌控力。3.从概念上得知,Actor模型强调消息触发,更适合分布式场景,解耦了调用方和提供方(我这里演示的TPL Dataflow是进程内Actor模型)。      TPL Dataflow组件应对高并发,低延迟要求4.Golang使用的Channel类Actor模型,使用Channel进一步解耦了调用的参与方,你都不用关注下游提供者是谁。 Waiting For Next Article......

作为一名编程老兵,深知大家平时常用的是共享内存并发模型,开口闭口“多线程”,“锁”, 可能很多人并没有关注到Actor模型,微软进程内Actor TPL Dataflow香气侧漏,值得推荐。

多对比、多体验不同的编程风格,别有洞天。

本文内容和制图均为原创,文章永久更新地址请参阅左下角原文,如对您有所帮助,请不吝分享 。

专题相关:一网打尽

 你管这叫"线程安全"?

 Redis分布式锁抽丝剥茧

 .Net线程同步技术解读

 TPL Dataflow组件应对高并发,低延迟要求

 如何利用.NETCore向Azure EventHubs准实时批量发送数据?

扫码关注我们

不会让您失望的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
课程介绍:本课程旨在介绍Python Ray框架的基本概念、核心组件和应用,帮助学员理解并掌握Ray在分布式计算领域的应用,并在实际工作和生活中获得职业加成和思维提升。教学设计:本课程采用系统化的教学设计,结合理论讲解和实际案例演示,以帮助学员全面理解Ray的工作原理和核心特性。课程内容根据逻辑顺序进行组织,从基础概念到高级应用,循序渐进地引导学员掌握Ray的使用技巧和最佳实践。内容特色:重点介绍Ray的任务并行模型、对象存储和Actor模型,让学员理解并运用这些特性进行高效的分布式计算。强调实际应用案例,展示Ray在分布式机器学习、强化学习、推荐系统等领域的成功应用,激发学员的创造力和应用思维。讲解方式:课程讲解采用简洁明了的语言,结合图示和示例代码,帮助学员轻松理解和掌握Ray的概念和使用方法。通过实际案例演示,学员可以看到Ray在实际项目中的应用场景和效果,进一步加深理解。与其他同类课程的差异化:本课程专注于Python Ray框架的介绍和应用,注重深入讲解任务并行、对象存储和Actor模型等核心概念。通过实际案例和应用场景的讲解,将Ray的理论知识与实际应用相结合,帮助学员将所学知识应用到实际工作和生活中。课程收益:     参与本课程后,学员将获得以下收益:职业加成:掌握Ray的分布式计算能力,提升在职场上解决复杂问题和处理大规模数据的能力。思维提升:理解任务并行、对象存储和Actor模型的思维模式,培养分布式思维和并发编程的能力。实际应用:通过实际案例演示和练习,学员将能够将Ray应用于实际工作项目中,提高工作效率和解决问题的能力。通过本课程的学习,您将掌握Python Ray框架的核心概念和应用,获得在分布式计算领域的专业知识,以及在实际工作和生活中获得的职业加成和思维提升。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有态度的马甲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值