5. 共享栈模式 这种做法有什么好处?其实我们可以直接想想以前的方法(每个协程单独分配栈)有什么坏处好了: 以前的方法为每个协程都单独分配一段内存空间,因为是固定大小的,实际使用中协程并不能使用到这么大的内存空间,于是就会造成非常大的内存浪费(有同学一定会问为什么不用 Split Stack ,这个东西的性能有多垃圾有目共睹)。而且因为绝大多数协程使用的栈空间都极少,复制栈空间的开销非常小。 因为协程的调度是非抢占的(non-preempt),而在 libco 中,切换的时机都是做 I/O 的时候,并且只有在切换的时候才会去复制栈空间,所以开销也可控。 具体原理:我们一步步来看其调用,从其中明白他的原理 在协程环境初始化时,要先调用 (co_alloc_sharestack) 来分配共享栈的内容,其中第一个参数 count 是指分配多少个共享栈,stack_size 是指每个栈的大小 ,分配出来的结构名是 stShareStack_t 。 stShareStack_t 结构 继续阅读 >>


刘生玺 19/01/19 16:15:40
LRU和LFU LRU是最近最少使用页面置换算法(Least Recently Used),也就是首先淘汰最长时间未被使用的页面! LFU是最近最不常用页面置换算法(Least Frequently Used),也就是淘汰一定时期内被访问次数最少的页! frist,如何使用链表实现LRU(简单) 我们维护一个有序单链表,越靠近链表尾部的结点是越早之前访问的。当有一个新的数据被访问时,我们从链表头开始顺序遍历链表。 如果此数据之前已经被缓存在链表中了,我们遍历得到这个数据对应的结点,并将其从原来的位置删除,然后再插入到链表的头部。 如果此数据没有在缓存链表中,又可以分为两种情况: 如果此时缓存未满,则将此结点直接插入到链表的头部 如果此时缓存已满,则链表尾结点删除,将新的数据结点插入链表的头部。 这样我们就用链表实现了一个 LRU 缓存,是不是很简单? #include <iostream> #include <list> #include <vector&g 继续阅读 >>


刘生玺 19/01/18 15:41:25
1. BST的后序遍历序列 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同 后序遍历(左右根).最后一个节点一定是整个树的根节点,根据树与递归的关系,泛化而讲,他会是树的根节点(包括左子树,右子树等等).所以我们的思路就是先找到根,然后判断前部分(相当于左子树)是否小于根,后部分(相当于右子树)是否大于根即可 class Solution { public: bool VerifySquenceOfBST(vector<int> sequence) { int sz = sequence.size(); if (sz == 0) return false; return IsBST(sequence, 0, sz - 1); } //第一部分是左子树结点的值,它们都比根结点的值小 b 继续阅读 >>


刘生玺 19/01/14 18:11:23
散列思想 散列表就是我们平常说的哈希表,英文名叫"Hash Table",其基础依据就是: 散列表用的是数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种扩展,由数组演化而来。可以说,如果没有数组,就没有散列表。 这里还是直接使用老师的例子来说事吧.中间添加自己的思想就行了.自己想例子又得半天,而且我们的目标也不是想一个好例子,而是真正理解并掌握知识.对吧? 用一个例子来解释一下。假如我们有 89 名选手参加学校运动会。为了方便记录成绩,每个选手胸前都会贴上自己的参赛号码。这 89 名选手的编号依次是 1 到 89。现在我们希望编程实现这样一个功能,通过编号快速找到对应的选手信息。你会怎么做呢? 我们可以把这 89 名选手的信息放在数组里。编号为 1 的选手,我们放到数组中下标为 1 的位置;编号为 2 的选手,我们放到数组中下标为 2 的位置。以此类推,编号为 k 的选手放到数组中下标为 k 的位置。 因为参赛编号跟数组下标一一对应,当我们需要查询参赛编号为 x 的选手的时候,我们只需 继续阅读 >>


刘生玺 19/01/14 18:00:26
   二叉查找树由于在频繁的动态更新过程中,可能会出现树的高度远大于 log2n的情况,所以就会导致各个操作效率下降,最坏的情况下就会退化为链表,变为O(n).很明显,想要解决这个问题,有效的一种办法就是使得树的高度不要差很多,也就是平衡它.     最先发明的平衡二叉查找树是AVL树,(它严格符合平衡二叉查找树的定义,即任何节点的左右子树高度相差不超过 1,是一种高度平衡的二叉查找树。)但是在工程中,我们经常听到的通常是红黑树,而不是AVL树.那么为什么工程中都喜欢用红黑树,而不是其他平衡二叉查找树呢?     其实在这里,我们应该能有一些想法了.既然他严格按照规定执行,每次的插入,删除,都就会引发树的调整.调整的多了,自然会影响树的效率.那么红黑树又是怎样解决这个问题的呐? 其实,平衡二叉查找树中“平衡”的意思,其实就是让整棵树左右看起来比较“对称”、比较“平衡”,不要出现左子树很高、右子树很矮的情况。这样就能让整棵树的高度相对来说低一些,相应的插入、删除、查找等操作的效率高一些。 所以红黑树就是 继续阅读 >>


刘生玺 19/01/08 19:12:00
一、判断题 String字符串在创建后可以被修改。 ( 0 ) 引用一个类的属性或调用其方法,必须以这个类的对象为前缀。 ( 0 final 类名 ) 当调用一个正在进行线程的stop()方法时,该线程便会进入休眠状态。 ( 0 ) 如果一个类声明实现一个接口,但没有实现接口中的所有方法,那么这个类必须是abstract类。 ( 1 ) 构造函数名应与类名相同,返回类型为void。 ( 0 ) 把数组中元素按某种顺序排列的过程叫做查找。 ( 0 ) 对于abstract类,不能创建该类的对象。 ( 1 ) 所有异常都必须捕获。 ( 0 ) 可以使用protected修饰符来防止方法和数据被不同包的非子类访问。 ( 1 ) 在Java程序中,可以使用private来修饰一个类。 ( 1 ) 不允许使用final来修饰abstract方法。 ( 0 ) 可以使用protected修饰符来防止方法和数据被不同包的非子类访问。 ( 1 ) An e 继续阅读 >>


刘生玺 19/01/02 17:51:10
首先给出基本所有的信号,方便以后查询. *1 SIGHUP 终止 终止控制终端或进程 2 SIGINT 终止 键盘产生的中断(Ctrl-C) 3 SIGQUIT dump 键盘产生的退出 4 SIGILL dump 非法指令 5 SIGTRAP dump debug中断 6 SIGABRT/SIGIOT dump 异常中止 7 SIGBUS/SIGEMT dump 总线异常/EMT指令 8 SIGFPE dump 浮点运算溢出 9 SIGKILL 终 继续阅读 >>


刘生玺 19/01/01 16:59:51
实验: 数据库安全性实验 一、实验目的 创建表和用户管理 创建表单是数据库中最基本的操作,也是使用比较频繁的操作,因此必须掌握SQL的(CREATE语句)的使用方法。而对于用户的管理操作更是一名合格的DBA所必须掌握的.本实验就要求掌握并熟悉这两项基本技能. 用户权限管理 为了保证数据库的安全性,每个DBMS都为系统针对于每一个用户设计了权限管理来保证数据安全.本实验就要求掌握对用户权限管理的的操作方法。 二、实验环境 MYSQL 三、实验前准备 (1)准备电脑,课本(数据库系统概论第五版) (2)了解创建表单和用户管理的命令 (3)了解操作用户权限的命令 四、实验内容与步骤 创建表和用户管理 (1)登录MYSQL数据库,创建三个表 ① 在数据库Tattoo中创建三个表,分别是学生表Student、课程表Course、学生选课表SC,约束以及属性如课本79页。 1. SQL语句 drop database if exists Tattoo ; create database Tatto 继续阅读 >>


刘生玺 18/12/29 11:54:02
个人配置说明:5.7.24 MySQL Community Server (GPL),环境CentOS 7 1.MYSQL 不支持语句触发(for each statement),只支持行触发(for each row,新旧数据通过关键字new和old区别) 实验: 数据库存储和触发器实验 一、实验目的 理解,实现并逐渐熟悉存储过程的使用 存储过程(Stored Procedure)是指一组可编程的函数,是为了完成特定功能的SQL语句集,经编译创建并保存在数据库中,用户可通过指定存储过程的名字并给定参数(需要时)来调用执行。使用它的目的主要是它不用像SQL语句一样解释执行,而是相当于二进制文件直接运行即可,提高了效率. 掌握触发器的定义和使用 触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合。这在实际使用过程中非常实用.作为一名合格的数据库管理人员,是必须要掌握的.这节实验的目的也在于此. 二、实验环境 MYSQL 三、实验前准备 (1)准备电脑,课本(数据 继续阅读 >>


刘生玺 18/12/29 11:47:19
协程实现原理 协程的本质都是通过修改 ESP 和 EIP 指针来实现的。其理论上还是单线程在运行. 程序在CPU上运行时依赖3个寄存器: ESP寄存值指向当前栈顶地址,指向当前指令需要的数据 EBP指向当前活动栈帧的基地址 指令寄存器IP,指向当前需要运行的指令 其中主要有(IP,ESP)寄存器最重要,这两个寄存器指针的改变可以修改当前需要加载到 CPU 运行的指令和数据,当某个操作陷入到耗时的等待中时,通过修改这两个指针即可让出CPU,交给其他的任务去使用,每个任务都必须主动的让出CPU,然后等待下一次的调度来继续未完成的任务,这样就可以最大程度的利用CPU,当一个任务等待过程非常短的时候,就出现了多个任务并行运行的效果,也就是协程。 实现协程的多种方法 利用 glibc 的 ucontext 组件(云风的库) 使用汇编来切换上下文(实现miniC协程,腾讯libco) 利用C语言语法switch-case的奇淫技巧来实现(Protothreads) 利用了 C 语言的 setjmp 和 lon 继续阅读 >>


刘生玺 18/12/20 22:56:00