当前位置:首页 > 单片机 > 架构师社区
[导读]面试官您好,我是来面试的 您好,我是这次的面试官,先介绍一下自己把 我是女孩,blala .... 那问一个多线程的问题吧,在一个多线程的环境中,怎么能保证一系列方法的执行顺序呢? 0 1 PART 题目 比如我们有三个方法,类似以下代码 static void Methond1()   

面试官您好,我是来面试的

进击谷歌:多线程下程序执行顺序怎么稳定不乱?
进击谷歌:多线程下程序执行顺序怎么稳定不乱?

您好,我是这次的面试官,先介绍一下自己把

进击谷歌:多线程下程序执行顺序怎么稳定不乱?
进击谷歌:多线程下程序执行顺序怎么稳定不乱?

我是女孩,blala ....

进击谷歌:多线程下程序执行顺序怎么稳定不乱?
进击谷歌:多线程下程序执行顺序怎么稳定不乱?

那问一个多线程的问题吧,在一个多线程的环境中,怎么能保证一系列方法的执行顺序呢?

进击谷歌:多线程下程序执行顺序怎么稳定不乱?
进击谷歌:多线程下程序执行顺序怎么稳定不乱?

0 1
PART
题目
进击谷歌:多线程下程序执行顺序怎么稳定不乱?

比如我们有三个方法,类似以下代码


static void Methond1()
        
{
            Console.WriteLine($"{Thread.CurrentThread.Name} 执行 第一个方法==");
        }
        static void Methond2()
        
{
            Console.WriteLine($"{Thread.CurrentThread.Name} 执行 第二个方法=======");
        }
        static void Methond3()
        
{
           Console.WriteLine($"{Thread.CurrentThread.Name} 执行  第三个方法=======");
        }
    }


分别初始化三个线程去执行这三个方法,每个线程执行的方法可以任意指定,但是方法的执行顺序必须是:Methond1=》Methond2=》Methond3

示例:

输入:3,2,1  
第一个线程执行方法3,第二个线程执行方法2,第三个线程执行方法1
输出:Methond1的输出=》Methond2的输出=》Methond3 的输出 ,即:
xxx执行 第一个方法==
xxx执行 第二个方法==
xxx执行 第三个方法==

面试官大哥,我好像不会哦

进击谷歌:多线程下程序执行顺序怎么稳定不乱?
进击谷歌:多线程下程序执行顺序怎么稳定不乱?

没关系,留下你的联系方式,如果可以,我们会有后续人员联系你的,感谢你来面试

进击谷歌:多线程下程序执行顺序怎么稳定不乱?
进击谷歌:多线程下程序执行顺序怎么稳定不乱?

进击谷歌:多线程下程序执行顺序怎么稳定不乱?        

  


02
PART
题解分析
进击谷歌:多线程下程序执行顺序怎么稳定不乱?

这道题本质上考的是多线程环境资源竞争的问题,在多线程环境下要想以固定某个顺序执行方法,必须要有一个类似屏障的东西来阻止不该执行的线程,或者换句话说必须要有一个机制来顺序化多个线程。这也是我们平时多线程开发环境中必须要面对的问题,现代服务器的cpu都是多核心,我们平时用的最多的java,c#等高级语言是能够利用服务器多核心这个优势的,这里是一个进程内,多线程就可以利用多核心。当然也有一些别的技术,比如Nodejs,虽然执行是单线程的,但是可以利用多进程来提高多物理cpu的利用率。


说的有点远了,接下来还是看这道题,这道题目考验的是多线程下资源的竞争问题和线程间的通信问题,说的直白一点就是:Methond1未执行之前,任何方法都不能执行(这里是指方法内的代码),Methond1执行完之后,会通知执行Methond2的线程,Methond2开始执行,Methond2执行完毕会通知执行Methond3的线程,以此类推。所以这道题的关键在于阻塞某个线程执行和通知某个线程执行。


在很多语言中都提供了lock的机制,或者信号量的机制。这些都是可以实现线程间通信的的解决方案,当然最简单暴力的方式还是通过共享变量的方式来实现通知,虽然有很多缺陷,但是在很多情况下确实是最简单快捷的方案。下边就以c#语言为例:

class Program
    {
        //把三个方法分别对应到 委托,为了方便执行方法
        static Action FirstAction = Methond1;
        static Action SecondAction = Methond2;
        static Action ThirdAction = Methond3;

        static Dictionary<int, Action> ActionDic = new Dictionary<int, Action>() { { 1, FirstAction }, { 2, SecondAction }, { 3, ThirdAction } };
        static void Main(string[] args)
        
{
            while (true)
            {
                Console.WriteLine("请输入顺序");
                var inputStr = Console.ReadLine();
                IsFinish1 = IsFinish2 = false;

                var input = inputStr.Split(",").Select(s => int.Parse(s));
                foreach (var i in input)
                {
                    var method = ActionDic.GetValueOrDefault(i);
                    Thread t = new Thread(method.Invoke);
                    t.Name = "线程" + i;

                    Console.WriteLine($"{t.Name} 执行方法 {method.Method.Name}");
                    t.Start();
                }
            }
        }

        static object objLock = new object();
        static bool IsFinish1 = false//第一方法是否执行完毕
        static bool IsFinish2 = false//第二方法是否执行完毕


        static void Methond1()
        
{
            Console.WriteLine($"{Thread.CurrentThread.Name} 执行 第一个方法==");
            IsFinish1 = true;

        }
        static void Methond2()
        
{
            while (true)
            {
                if (IsFinish1)
                {
                    Console.WriteLine($"{Thread.CurrentThread.Name} 执行 第二个方法=======");
                    IsFinish2 = true;
                    break;
                }
            }
        }
        static void Methond3()
        
{
            while (true)
            {
                if (IsFinish2)
                {
                    Console.WriteLine($"{Thread.CurrentThread.Name} 执行  第三个方法=======");
                    break;
                }
            }
        }
    }

测试执行:

请输入顺序
2,3,1
线程2 执行方法 Methond2
线程3 执行方法 Methond3
线程1 执行方法 Methond1
请输入顺序
线程1 执行 第一个方法==
线程2 执行 第二个方法=======
线程3 执行  第三个方法=======
3,2,1
线程3 执行方法 Methond3
线程2 执行方法 Methond2
线程1 执行方法 Methond1
请输入顺序
线程1 执行 第一个方法==
线程2 执行 第二个方法=======
线程3 执行  第三个方法=======

不要太纠结以上的代码,以上只是作为抛砖引玉的作用,就算是有执行错误,思路我觉得还是没有问题的,当然确实有很多要优化的地方,比如等待执行的线程一直在耗费cpu资源的情况,可以替换为自旋锁或者混合锁,有兴趣的同学可以进行优化一番。

       

进击谷歌:多线程下程序执行顺序怎么稳定不乱?        



03
PART
公司简介
进击谷歌:多线程下程序执行顺序怎么稳定不乱?

但是,作为语法很优秀的c#怎么能就此止步呢?c#本身提供了Task的机制,可以把它看做是类似golang的协程(虽然不是很像)。基于task的机制我们很容易就完成,task的 ContinueWith机制就是为此而生的,它可以很方便的把多个并行的task串行化,有兴趣的同学可以试一下,但是我要说的并非ContinueWith。既然要执行的顺序化,如果我把执行的代码放在有顺序的容器中,然后按照顺序去执行,岂不快哉?不多废话:

class TaskTest
    {
        static Func<Task> FirstAction = Methond1;
        static Func<Task> SecondAction = Methond2;
        static Func<Task> ThirdAction = Methond3;
        static Dictionary<int, Func<Task>> ActionDic = new Dictionary<int, Func<Task>>() { { 1, FirstAction }, { 2, SecondAction }, { 3, ThirdAction } };
        static Func<Task>[] tList = new Func<Task>[3];
       public static void Start()
        
{
            while (true)
            {
                Console.WriteLine("请输入顺序");
                var inputStr = Console.ReadLine();

                var input = inputStr.Split(",").Select(s => int.Parse(s));
                foreach (var i in input)
                {
                    var method = ActionDic.GetValueOrDefault(i);
                    tList[i-1] = method;
                }
                foreach (var t in tList)
                {
                    t.Invoke().Wait();
                }
            }
        }

        static Task Methond1()
        
{
           return Task.Run(()=> {
                Console.WriteLine($"{Thread.CurrentThread.Name} 执行 第一个方法==");
            });
        }
        static Task Methond2()
        
{
           return  Task.Run(() => {
                Console.WriteLine($"{Thread.CurrentThread.Name} 执行 第二个方法=======");
            });
        }
        static Task Methond3()
        
{
            return Task.Run(() => {
                Console.WriteLine($"{Thread.CurrentThread.Name} 执行  第三个方法=======");
            });
        }
    }


测试:

请输入顺序
2,3,1
执行 第一个方法==
执行 第二个方法=======
执行  第三个方法=======
请输入顺序
3,2,1
执行 第一个方法==
执行 第二个方法=======
执行  第三个方法=======
请输入顺序
1,3,2
执行 第一个方法==
执行 第二个方法=======
执行  第三个方法=======
请输入顺序

是不是很爽,毫不犹豫的说c#是一门很优秀的语言,在并发方面做的很优秀。以上Task的代码并非是最优代码,比如 可以用Await来代替 wait(),这样的话在真实环境中可以释放当前线程来提高吞吐量,记住:await方式提高的吞吐量,并非缩短了单次请求的执行时间。

进击谷歌:多线程下程序执行顺序怎么稳定不乱?        

      

        

助你早日进入谷歌!!!


特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:

进击谷歌:多线程下程序执行顺序怎么稳定不乱?

长按订阅更多精彩▼

进击谷歌:多线程下程序执行顺序怎么稳定不乱?

如有收获,点个在看,诚挚感谢


免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭