递归调用

iOS: 线程中那些常见的锁

拟墨画扇 提交于 2019-12-02 06:13:15
一、介绍 在多线程开发中,锁的使用基本必不可少,主要是为了解决资源共享时出现争夺而导致数据不一致的问题,也就是线程安全问题。锁的种类很多,在实际开发中,需要根据情况选择性的选取使用,毕竟使用锁也是消耗CPU的。 本人虽然一直有使用多线程进行开发,但是对于锁的使用和理解并不是特别的深入,这不看到一篇挺mark的博客: https://www.jianshu.com/p/a236130bf7a2 ,在此基础上稍添加点东西转载过来(尊重原创),一是为了记录便于随时翻阅,而是为了写一遍加深印象,知识都是一个copy和attract的过程。 二、种类 1、互斥锁 概念:对共享数据进行锁定,保证同一时刻只能有一个线程去操作。 抢到锁的线程先执行,没有抢到锁的线程就会被挂起等待。 等锁用完后需要释放,然后其它等待的线程再去抢这个锁,那个线程抢到就让那个线程再执行。 具体哪个线程抢到这个锁是由cpu调度决定的。 常用: @synchronized:同步代码块 example:执行操作 /** *设置属性值 */ -(void)setMyTestString:(NSString *)myTestString{ @synchronized(self) { // todo something _myTestString = myTestString; } } example:创建单例 //注意

递归

柔情痞子 提交于 2019-12-02 05:27:14
递归   递归,就是在当前方法内调用自己的这种现象,也可以调用别的方法。   实例:     1.斐波那契数列的兔子   1 public static int rabbit(int n){ 2 if(n==1){ 3 return 1; 4 } 5 if(n==2){ 6 return 1; 7 } 8 return rabbit(n-1)+rabbit(n-2); 9 }     2. 遍历一个目录下所有文件夹和文件       先定义一个类继承FilenameFilter过滤器接口:MyFilter.java 来判断是否有文件夹和文件       然后获取该目录下所有文件和文件夹的File数组       开始遍历,如果该file是文件夹则继续递归找到下一级的所有文件和文件夹,如果是文件直接打印输出     部分代码展示: public static void get(File path){ //获取该目录下所有文件和文件夹的File数组 File[] files=path.listFiles(new MyNameFilter()); //遍历 for(File file:files){ //如果该file是文件夹则继续递归找到下一级的所有文件和文件夹 if(file.isDirectory()){ get(file); }else{ //如果是文件直接打印输出 System

Linux中的各种锁及其基本原理

风流意气都作罢 提交于 2019-12-02 04:56:37
Linux中的各种锁及其基本原理 1.概述 通过本文将了解到如下内容: Linux系统的并行性特征 互斥和同步机制 Linux中常用锁的基本特性 互斥锁和条件变量 2.Linux的并行性特征 Linux作为典型的多用户、多任务、抢占式内核调度的操作系统,为了提高并行处理能力,无论在内核层面还是在用户层面都需要特殊的机制来确保任务的正确性和系统的稳定运行,就如同一个国家需要各种法律条款来约束每个公民的行为,才能有条不紊地运转。 在内核层面涉及到各种软硬件中断、进线程睡眠、抢占式内核调度、多处理器SMP架构等,因此内核在完成自己工作的时候一直在处理这些资源抢占的冲突问题。 在用户层面的进程,虽然Linux作为虚地址模式操作系统,为每个进程开辟了独立的虚拟地址空间,伪独占式拥有资源,但是仍然存在很多场景不得不产生多个进程共享资源的问题,来完成进程间的通信,但是在Go语言中进程间的通信使用消息来完成,处理地更优雅一些。 在线程层面,线程作为进程的一部分,进程内的多个线程只拥有自己的独立堆栈等少量结构,大部分的资源还是过线程共享,因此多线程的资源占用冲突比进程更加明显,所以多线程编程的线程安全问题是个重难点。综上可知,无论在kernel还是user space都必须有一些机制来确保对于资源共享问题的解决,然后这个机制就是接下来要说的:同步和互斥。 3.同步和互斥机制 基本概念

未关中断情况下的hardlock

风格不统一 提交于 2019-12-02 03:26:57
最近遇到一例crash,3.10内核,hardlock,查看对应的堆栈,中断是使能的。 查看对应的hrtimer_interrupts和hrtimer_interrupt_save的值,发现确实相等。 具体可参考: 百思不得其解,然后咨询os的同事茂春兄,然后他很轻描淡写第说,他遇到过,并随手给了个链接: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/kernel/watchdog.c?id=7edaeb6841dfb27e362288ab8466ebdc4972e867 你看,多个兄弟多么关键,搞内核,永远不要一个人战斗。 另外,顺带看了一下touch_nmi_watchdog的用法,比如为了避免在printk的时候,遇到nmi,nmi中有可能调用printk,这样就非递归情况下变成死锁了, 那么printk调用一下touch_nmi_watchdog,安抚一下那只狗狗。 来源: https://www.cnblogs.com/10087622blog/p/11728836.html

算法一看就懂之「 递归 」

那年仲夏 提交于 2019-12-02 02:28:02
之前的文章咱们已经聊过了 「 数组和链表 」 、 「 堆栈 」 和 「 队列 」 ,今天咱们来看看「 递归 」,当然「 递归 」并不是一种数据结构,它是很多算法都使用的一种编程方法。它太普遍了,并且用它来解决问题非常的优雅,但它又不是那么容易弄懂,所以我特意用一篇文章来介绍它。 一、「 递归 」是什么? 递归 就是指函数直接或间接的调用自己,递归是基于栈来实现的。递归的经典例子就是 斐波拉契数列(Fibonacci)。一般如果能用递归来实现的程序,那它也能用循环来实现。用递归来实现的话,代码看起来更清晰一些,但递归的性能并不占优势,时间复杂度甚至也会更大一些。 上图为 斐波拉契数列 图例。 要实现递归,必须满足2个条件: 可调用自己 就是我们要解决的这个问题,可以通过函数调用自己的方式来解决,即可以通过将大问题分解为子问题,然后子问题再可以分解为子子问题,这样不停的分解。并且大问题与子问题/子子问题的解决思路是完全一样的,只不过数据不一样。因此这些问题都是通过某一个函数去解决的,最终我们看到的就是不停得函数调用自己,然后就把问题化解了。 如果这个问题不能分解为子问题,或子问题的解决方法与大问题不一样,那就无法通过递归调用来解决。 可停止调用自己 停止调用的条件非常关键,就是大问题不停的一层层分解为小问题后,最终必须有一个条件是来终止这种分解动作的(也就是停止调用自己)

2019-2020-1学期 20192406 《网络空间安全专业导论》第三周学习总结

纵饮孤独 提交于 2019-12-01 23:31:49
第六章 低级程序设计语言与伪代码 6.1 计算机操作 我们所用的程序设计语言都必须反映出计算机能够执行的操作类型。让我们通过重述计算机的定义来开始新的讨论:计算机是能够存储、检索和处理数据的可编程电子设备。 这个定义中的操作字包括 可编程的 、 存储 、 检索 和 处理 。上一章指出了数据和操作数据的指令逻辑上是相同的,它们存储在相同的地方。这就是“可编程的”这个词的意义所在。操作数据的指令和数据一起存储在机器中。要改变计算机对数据的处理,只需要改变指令即可。 存储、检索和处理 是计算机能够对数据执行的动作。也就是说,控制单元执行的指令能够把数据 存储 到机器的内存中,在机器内存中 检索 数据,在算术逻辑单元中以某种方式 处理 数据。词语“处理”非常通用。在机器层,处理涉及在数据值上执行算术和逻辑操作。 6.2 机器语言 机器语言 :由计算机直接使用的二进制编码指令构成的语言 Pep/8:一台虚拟机 虚拟机 :为了模拟真实机器的重要特征而设计的假想机器 Pep/8反应的重要特征 回忆第5章中所说的,寄存器是中央处理器中算术/逻辑单元的一小块存储区域,它用来存储特殊的数据和中间值。Pep/8有七个寄存器,我们重点研究其中三个: 程序计数器(PC) , 其中包含下一条即将被执行的指令的地址。 指令寄存器(IR) , 其中包含正在被执行的指令的一个副本。 累加器 (是一个寄存器)。

递归

别等时光非礼了梦想. 提交于 2019-12-01 20:54:34
递归方法 待整理,未完… 递归的定义: 递归调用是一种特殊的嵌套调用,是某个函数调用自己或者是调用其他函数后再次调用自己的,只要函数之间相互调用能产生循环的则一定是递归调用。 一个递归算法必须包括 终止条件 和 递归部分 。 相关的题目 递归函数中的形参是() A.自动变量 B.外部变量 C.静态变量 D.可根据需要自动以存储类型 存储类型有: auto static register extern 递归式借助栈来实现的,自动变量是存储在栈里面的,随着递归的进行,自动创建和销毁。 外部变量和静态变量是不能作为递归函数的参数的。自动变量大体上等价于局部变量,但也不完全相同 只有那种使用了局部变量的递归过程在转换成非递归过程时,才必须使用栈() A.对 B.错 递归工作栈里面包括返回地址、本层的局部变量和递归调用的形参代换用实参,所以正常情况下,无论递归过程有没有使用局部变量,转换为非递归过程都需要用栈来模拟这个递归调用过程。 递归程序优化的一般手——尾递归优化 斐波那契数列的两种递归方法 # 一般递归方法 def fab ( n ) : if ( n < 3 ) : return 1 else : return fab ( n - 1 ) + fab ( n - 2 ) # 具有‘线性迭代过程’特性的递归——尾递归过程 def fab1 ( n , b1 = 1 , b2 = 1 ,

php 使用递归的三种手法

感情迁移 提交于 2019-12-01 20:54:17
递归:函数自己调用自己的一种编程方法,类似于循环,所以递归调用的函数中必须有终止条件,否则就会成为死循环 无限级:其实并不是真正的无限级,只是层级不确定,所以我们称之为无限级 因为常用递归实现无限级分类,所以我们习惯说无限级的时候带上分类。 递归的三种常用技法: 静态变量、全局变量、引用 一 静态变量方式 function loop(){ static $i = 0; echo $i.' '; $i++; if($i<10){ loop(); } } loop();//输出 0 1 2 3 4 5 6 7 8 9 二 全局变量方式 $i = 0; function loopGlobal(){ global $i; echo $i.' '; $i++; if($i<10){ loopGlobal(); } } loopGlobal();//输出 0 1 2 3 4 5 6 7 8 9 三 引用传参方式 function loopReference(&$i=0){ echo $i.' '; $i++; if($i<10){ loopReference($i); } } loopReference();//输出 0 1 2 3 4 5 6 7 8 9 递归经常被用在处理无限级的问题上,通过以上三种手法再结合实际情况,灵活运用就可以解决自己的无限级问题。如果你是新手

利用静态变量记录并控制递归函数的执行次数

ぐ巨炮叔叔 提交于 2019-12-01 20:53:29
static 关键字 在PHP的函数内部中,当我们定义一个 static 变量时,需要对该变量进行初始化赋值且仅初始化一次,由于static修饰的变量是局部的,该变量仅在函数内部有效,当每次调用该函数时,该变量的值都会保留。 利用这一特性,可以统计出递归函数的调用次数,并可以做限制,防止未收敛的递归函数无限执行下去,造成死循环。 下面可以通过递归方法常用的 求斐波那契数列 与 快速排序 做演示: 斐波那契数列 $num = 10; echo "fibonacciSequence($num)的值为:".fibonacciSequence($num); echo PHP_EOL; function fibonacciSequence($num) { $limitCount = 1000; static $executeCount = 0; $executeCount++;//static变量在函数内完成初始化后,每次执行该函数变量值都会保留,利用这一特性可以记录函数调用次数 echo "函数".__METHOD__."已递归执行{$executeCount}次;".PHP_EOL; if($executeCount < $limitCount)//递归执行次数未超过函数限定次数方可继续递归下去 { if($num == 1) { return 1; } else if($num ==

用静态数组在函数递归过程中保存中间数据(以递归输出斐波那契数列为例——详细注释)

核能气质少年 提交于 2019-12-01 20:52:45
通过建立一个静态数组来保存递归函数调用过程中产生的中间数据,可以规避掉很多不必要的重复计算, 能在很大程度上提高程序的运行效率,尤其是在动态规划等需要递归调用的算法中应用广泛。 下面以递归输出斐波那契数列为例, 通过建立一个静态数组,来使得程序运行避免超时。 #include<stdio.h> long int count[1000];//establish an array to store the temporary data during the recursion calculation. long int fibo(int i) { if (i == 2 || i == 1) return 1; else if(count[i - 1] != 0 && count[i - 2] != 0) { return count[i - 1] + count[i - 2]; }// take a value from the array before assigning a value to the array to reduce the unnecessary judgement. else { count[i - 1] = fibo(i - 1); count[i - 2] = fibo(i - 2); return count[i - 1] + count[i - 2]; }