杂碎知识点(一)

本博客内容:
一、运算符优先级
二、静态方法能不能重写
三、同步异步的理解,什么场景
四、什么情况下不能用索引
五、内存泄漏以及常见的解决方法
六、Git版本控制工具,命令行提交代码步骤
七、C++多线程同步(关键段、事件、互斥量、信号量)的使用
八、单例模式
九、linux正则表达式使用grep awk sed

一、运算符优先级

https://blog.csdn.net/nicky_zs/article/details/4053146
 后缀比前缀高。
 左移右移 > 比较 > (== !=) & ^ | && || ::? 各种赋值

二、静态方法能不能重写

https://blog.csdn.net/ycb1689/article/details/17163273
  可以被继承,不能被重写,父类中有一个static fun,子类也有一个一模一样的static fun,那么该子类的方法会把原来继承过来的父类隐藏掉,而不是重写。就是这2个方法没关系,不存在多态的性质。

三、同步异步的理解,什么场景

https://blog.csdn.net/ideality_hunter/article/details/53453285
  同步:所有的操作都做完,才返回给用户。即写完数据库之后,再返回给相应用户,用户体验不好。
  异步:将用户请求放入消息队列,并反馈给用户。不用等所有操作做完,就产生相应用户请求。即先响应用户请求,然后慢慢去写数据库,用户体验较好。
  异步例子:
为了避免短时间大量的数据库操作,就使用缓存机制,就是消息队列。先将数据放入消息队列,然后再慢慢写入数据库。
  引入消息队列机制,虽然可以保证用户请求的快速响应,但是并没有使得数据迁移的时间变短。用户输入完http url请求之后,就可以把浏览器关了,干别的去了,如果不用redis,浏览器不能关闭。
同步例子:
银行的转账功能
https://blog.csdn.net/lxcao/article/details/52751955
举例子:生活费问题: 同步:一直打电话call 异步:发个短信
同步:提交请求→等待服务器处理→处理完毕返回 这个期间浏览器不能干别的
异步:请求通过事件触发→服务器处理→处理完毕 浏览器可以干别的
https://blog.csdn.net/qq_21033663/article/details/51564786

异步适用场景:
  1.不涉及资源共享,或对共享资源只读,即非互斥操作
  2.没有时序性要求
  3.不需要原子操作
  4.常用于IO耗时操作,比较影响客户体验
  5.不影响主线程逻辑

同步适用场景:非异步的时候
  好处:1、更简单,就近处理 2、同步流程对结果的处理始终和前文保持在一个上下文内。
3、同步流程可以很容易捕获、处理异常 4、同步流程是最天然的控制过程顺序执行的方式

异步好处:
  1、可以立即给调用方返回结果2 、可以延迟给调用方最终的结果数据3、可以释放占用的线程等资源,避免阻塞,等到结果产生再重新获取线程处理 3、可以等多次调用的结果出来后,再统一返回一次结果集合,提高响应效率。

四、什么情况下不能用索引

 1、表很小的情况,没必要
 2、如果表数据需要频繁修改,不建议使用索引
 3、如果查询返回记录很多,不建议使用索引
索引失效:
 http://www.cnblogs.com/hongfei/archive/2012/10/20/2732589.html
 1、条件中有or (所以说少用or)
 2、like查询是以%开头的
 3、如果列类型是字符串,那么一定要在条件中将数据使用引号引用起来,否则不使用索引。
 4、如果mysql估计使用全表扫描要比索引快,则不使用索引。

五、内存泄漏以及常见的解决方法

https://blog.csdn.net/na_he/article/details/7429171
1、什么是内存泄漏
  由于疏忽或者错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因此造成了内存的浪费。
2、对于C/C++没有垃圾回收机制的语言,来讲,要关注2类的泄漏:
  ①堆内存泄漏:
  ②系统资源泄漏:主要是指分配的比如Bitmap,handle,socket等没有使用相应的函数释放掉,导致系统资源的浪费。严重可导致系统效能降低,系统运行不稳定。
3、如何解决
  困难在于
  1.编译器不能发现
  2.运行时才能捕获这些错误,没有明显的症状
  3.对于手机等终端开发用户来说,尤为困难。
从三个方面解决:
第一:良好的编码习惯,尽量在设计内存的程序段,检查出内存泄漏。使用了内存分配的函数,要记得用相应的函数释放掉,一旦使用完毕。
第二,重载new和delete,也是大家编码中经常使用的方法
主要思路:将分配的内存以链表的形式自行管理,使用完毕之后从链表中删除,程序结束时可检查该链表,其中记录了内存泄漏的文件,所在文件的行数以及泄漏的大小。
第三,boost中的smart pointer
第四,一些常见的工具插件
由内存泄漏引出的内存溢出问题:
内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是会产生内存溢出的问题。
常见的溢出有:
1.内存分配未成功,却使用了它。
解决办法:使用内存之前检查指针是否为NULL,如果指针p是函数的参数,那么在函数的入口处用assert(p!=NULL)来进行检查,如果是用malloc或new来申请内存,应该用if(p==NULL)来防止。
2.内存分配虽然成功,但是尚未初始化就使用了它
3.内存分配成功,也初始化了,但操作越过了内存的边界
4.使用free或者delete释放内存后,没有将指着设置为NULL。导致了“野指针”
不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。

六、Git版本控制工具,命令行提交代码步骤

https://blog.csdn.net/qq_34801506/article/details/80498007
1.安装git
2.配置path环境变量
cmd→git,查看path环境变量是否配置成功
相关命令: git config –list git config -global git config -system
配置全局变量:git config -global user.name “tiemao”
配置全局变量邮箱:git config -global user.name “[email protected]
配置编辑器:git config -global core.editior “vim”
配置merge工具: git config -global merge.tool vimdiff
3.git clone url 从github上克隆项目
4.提交代码
git status
git add . (一定要加.)
git status
按下“”i” 录入commit信息(按照模板进行填写log信息)
按下“esc”
切换输入法为英文,输入“:wq”
git pull
git push
5.获取帮助:git help config
https://www.cnblogs.com/chrischen123/p/5912442.html
1.git和svn的区别?
 ①很多时候,git速度比svn更快
 ②SVN是集中式管理,GIT是分布式管理
 ③SVN使用分支比较笨拙,GIT可以轻松拥有多个分支
 ④SVN必须联网才能正常工作,GIT支持本地版本控制工作
 ⑤分布式和集中式的最大区别:分布式的时候,开发者可以本地提交代码;每个开发者机器上都有一个服务器的数据库。
2.git使用
 git init(初始化)
 git config user.name user.email 配置 加上global配置全局
 git commit -m “描述”
3.git工作原理
(1)工作区:仓库文件里除了.git目录以外的文件
(2)版本库:.git目录,用于存储记录版本信息
暂存区(stage/Index)
分支(master):git自动创建的分支。
HEAD指针:用于指向当前分支;

七、C++多线程同步(关键段、事件、互斥量、信号量)的使用

https://www.cnblogs.com/codingmengmeng/p/5913068.html
  C++本身没有提供多线程机制,当前C++11新特性中,可以使用std::thread来创建线程。但是windows提供了相关API,可以进行多线程编程。

  调用函数声明 DWORD WINAPI Fun(LPVOID lpParam)
HANDLE CreateThread(安全性,栈空间,函数,参数,0表示创建后激活,线程ID);
多线程文章系列
  https://blog.csdn.net/morewindows/article/details/7392749
CreateThread()和_beginthreadex()函数有什么区别?
  头文件:#include windows.h #include process.h
  一个是windows的API接口,在c/c++语言中的函数
_beginthread()函数在创建新线程时会分配并初始化一个_tiddata块。这个_tiddata块自然是用来存放一些需要线程独享的数据。事实上新线程运行时会首先将_tiddata块与自己进一步关联起来。然后新线程调用标准c运行库如strerror()就会先取得_tiddata块的地址再将需要保护的数据存入_tiddata块中。这样每个线程就只会访问和修改自己的数据不会去篡改其他线程的函数了。因此如果在代码中有使用标准c运行库中的函数时,尽量使用_beginthreadex()函数来代替CreateThread().
经典的多线程同步问题:

问题:主线程启动10个子线程并将子线程序号的变量地址作为参数传递给子线程,子线程接受参数→sleep(50)→全局变量++→sleep(0)→输出参数和全局变量

要求:子线程输出的线程序号不能重复。
全局变量的输出必须递增

考察点:
1、主线程应等待子线程保存完毕之后才能改动该参数并启动下一个线程。涉及主线程和子线程的同步。
2、子线程之间会互斥的改动和输出全局变量。要求全局变量的输出必须递增。涉及到各子线程间的互斥。
输入序列的混乱引入解决办法:
1:关键段CS
4个函数:参数均为指针类型的关键段变量
void InitializeCriticalSection( ); //定义关键段后必须初始化
void DeleteCriticalSection(); //用完之后记得销毁
void EnterCriticalSection() ; //系统保证各线程互斥的进入关键区域
void LeaveCriticalSection(); //离开关键区域
注意:
关键段是有“线程所有权”概念的,会记录拥有该关键段的线程句柄。
可将关键段比作房卡,调用EnterCriticalSection()即申请房卡,得到房卡后当然是可以多次进出房间的。在你调用LeaveCriticalSection()交出房卡之后,别人自然是无法进入该房间的。该程序中因为主线程拥有线程所有权,即房卡,所以它可以重复进入关键段代码区域从而导致子线程在接受参数之前就已经修改了这个参数。关键段可以用于线程间的互斥,但不可以用于同步
总结:
1.关键段4个函数。
2.关键段可以解决线程的互斥问题,但因为具有“线程所有权”,无法解决同步问题。
3.推荐关键段与旋转锁配合使用。
2.事件event
是个内核对象。使用方便。
1.CreateEvent() 创建事件 安全性 TRUE手动置位 /FALSE自动置位 如果为自动置位,则对该事件调用waitforsingleobjects()后会自动调用resetEvent()使事件变成未触发状态。
参数3:事件初始状态(TRUE已触发) 参数4:表示事件的名称()NULL表示空事件
2.OpenEvent()
3.setEvent() 触发事件
4.ResetEvent( ) 将事件设置为未触发
5.PluseEvent() 将事件触发后立即将事件设置为触发状态,相当于触发一个事件脉冲。

总结:
事件是内核对象,事件分为手动置位和自动置位事件。(事件evnet)内部它包含一个使用计数(所有内核对象都有),一个布尔值表示是手动置位事件还是自动置位事件。另一个布尔值用来标识有无触发。
事件可以解决线程间的同步问题,因此也能解决互斥问题。
3:互斥量
互斥量是一个内核对象,用来确保一个线程独占一个资源的访问。
互斥量与关键段的行为相似。可以用于不同进程间的线程互斥访问资源。
主要用到4个函数:
1.CreateMutex() 参数: 安全控制NULL,确定互斥量的初始拥有者,互斥量的名字
调用成功返回一个互斥量的句柄。失败返回NULL。
2.OpenMutex() 打开互斥量: 参数:访问权限,句柄继承性,参数名称。
调用成功返回一个互斥量的句柄。失败返回NULL。
3.ReleaseMutex() 触发互斥量
说明:访问互斥资源应该要调用等待函数,结束访问时要调用ReleaseMutex()来标识访问结束。
4.使用完毕,CloseHandle()清理即可。

互斥量也不同解决线程间的同步问题。
因为互斥量也有线程所有权的概念。
总结:
1.互斥量是内核对象,它与关键段都有“线程所有权”,不能用于线程的同步
2.互斥量能够处理多个进程之间的线程互斥。
4:信号量semaphore
有三个函数:
CreateSemaphore:创建信号量
OpenSemphore:打开信号量
ReleaseSemaphore:释放信号量
当前资源数量大于0,表示信号量处于触发状态,等于0表示信号量已经耗尽,故信号量未触发。
多线程中用一个信号量和一个关键段,信号量用于处理主线程与子线程的同步,用关键段来处理各子线程间的互斥。
信号量可以解决线程间的同步问题。
https://blog.csdn.net/morewindows/article/details/7538247
总结:

1.线程同步的主要任务:
  答:在引入多线程后,由于线程执行的异步性,会给系统造成混乱,特别是在急用临界资源时,如果多个线程急用同一台打印机,会使打印结果交织在一起,难于区分。当多个线程急用共享变量,表格,链表时,可能会导致数据处理出错。因此,主要任务是使并发执行的各线程之间能够有效的共享资源和相互合作。从而使得程序的执行具有可再现性。
2.
  当线程并发执行时,由于资源共享和线程协作,使用线程之间会存在以下两种制约关系。
1.间接相互制约:一个系统中的多个线程必然要共享某种系统资源,如cpu,共享IO设备。例如A用打印机,其他都要等着。
2.间接相互制约:主要是因为线程之间的合作,如有线程A将计算结果提供给线程B做进一步处理,那么线程B在线程A将数据送达之前,一直阻塞。
间接相互制约可以称为互斥。直接相互制约可以成为同步。
同步包括互斥,互斥是一种特殊的同步。
每个进程中访问临界资源的代码称为临界区。

关键段和互斥量都有“线程所有权”。

除了关键段,其他都是内核对象。可以跨进程使用。

八、单例模式

参考:https://www.cnblogs.com/damsoft/p/6105122.html
1概念:
 单例对象的类必须保证只有一个实例存在。
 举例:某服务器程序的配置信息放置在一个文件中,这些配置文件由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。简化了复杂环境下的配置管理。
实现要素:
 将类的构造函数为私有。
 私有静态引用指向自己的实例
 以自己实例为返回值的公有函数
2好处:
 由于在系统内存中只存在一个对象,可以节约系统资源,当需要频繁创建和销毁单例对象时,单例模式无疑可以提高系统的性能。
避免对共享资源的多重占用
3坏处:
 ①不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景中发生变化,单例就会引起数据的错误,不能保存彼此的状态。
 ②如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,导致对象状态的丢失。
4.注意事项:
 注意线程安全
 饿和懒单例模式都是私有的,不能被继承。有些单例模式是可被继承的(登记式模式)
适用场景:
 单例模式只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公有的场合适合适用。如多个模块使用同一个数据源连接对象等。
 1.频繁实例化然后销毁的对象
 2.创建对象时耗时过多、耗费资源过多,但又经常使用的对象
 3.频繁访问数据库或文件的对象
典型应用举例:
 1.windows的任务管理器:只能打开一个
 2.网站的计数器:否则难以同步
 3.应用程序的日志应用,一般都用单例模式实现。
原则和过程:
 1.确保一个类只有一个实例,自行实例化并向系统提供这个实例
 饿汉:类加载时就实例化一个对象给自己的引用
 懒汉:取得实例的方法才会实例化对象
懒汉式和饿汉式:
饿汉优点:
 线程安全
 类加载时就已经创建好了一个静态对象,调用时反映速度快。
缺点:
 资源效率不高,可能getInstance()永远都不被执行到。
懒汉优点:
 资源利用率高,不执行getInstance()就不会被实例。
缺点:
 单线程没问题,解决:加锁。第一次加载不够快。
推荐使用饿汉式。除非对资源十分在意。

九、linux正则表达式使用grep awk sed

1、grep:

参考:http://www.cnblogs.com/peida/archive/2012/12/17/2821195.html
http://www.cnblogs.com/end/archive/2012/02/21/2360965.html
grep命令:
强大的文本搜索工具
Global regular expression Print
权限:所有用户
工作方式
  一个或多个文件中搜索字符串模板。如果模板包括空格,则必须被引用,模板后的所有字符串被看做是文件名。搜索的结果被送到标准输出,不影响源文件内容。
可用于shell脚本,因为grep通过返回一个状态值来说明搜索的状态,如果模板搜索成功,则返回0。搜索不成功,返回1.如果搜索的文件不存在,则返回2
命令格式
  grep 选项 pattern file
命令功能
  用于过滤/搜索的特定字符。可使用正则表达式与多种命令配合使用。十分灵活。
命令参数
 -a 不要忽略二进制的数据
 -A 行数 after 显示该行之后的内容
 -B 行数 before 显示该行之前的内容
 -c count 计算符合样式的列数
 -C 行数 显示该行之前后的行内容
 -d 动作 当指定要查找的是目录而非文件时,必须使用这项参数,否则grep指令将回报信息并停止动作。
 -f 规则文件 指定规则文件,内容含有一个或多个规则样式,让grep查找符合规则条件的文件内容,格式为每行一个规则样式。
 -i 忽略字符大小写的差别
 -l 小写的L,列出文件内容符合指定的样式的文件名称
 -L 列出文件内容不符合指定的样式的文件名称
 -n 显示行号
 -v 显示不包含匹配文本的所有行
 -V 显示version版本信息
规则表达式
 grep的规则表达式:
^ 代表行的开始,如:’^grep’,匹配所有以grep开头的行
$ ‘grep$’ 匹配所有以grep结尾的行
. 匹配一个非换行符的字符 如 ‘gr.p’ 匹配一个后接一个任意字符,然后是p
* 匹配零个或多个先前字符 ‘ *grep’ 匹配一个或多个空格后紧跟grep的行。
.* 两个一起用, 代表任意字符这个是最常用的。
[ ] 匹配一个指定范围内的字符,如 ‘[Gg]rep’ 匹配Grep和grep
[ ^ ] 匹配一个不在指定范围内的字符,’[^A-FH-Z]rep’
(..) 标记匹配字符,如’(love)\’,love被标记为1
\< 表示单词的开始 匹配以grep开头的单词的行
\> 表示单词的结尾 匹配以grep结尾的行
这里写图片描述
\w 匹配文字和数字字符 也就是[A-Za-z0-9] 如:’G\w*p’
\W 匹配和\w是反置的 如点号句号等
\b 单词锁定符,如’\bgrep\b’ 只匹配grep
POSIX字符
为在不同国家的字符编码中保持一致,POSIX增加了特殊的字符类,如[:alnum:]
[ A-Za-z0-9] 的另外一种写法。要把它们放到[ ]号内才能成为正则表达式,如[A-Za-z0-9]或[ [:alnum:] ] 。在linux下的grep除fgrep外,都支持POSIX的字符类。
[:alnum:] 文字数字字符
[:alpha:] 文字字符
[:digit:] 数字字符
[:graph:] 非空字符(非空格、控制字符)
[:lower:] 小写字符
[:cntrl: ] 控制字符
[:print:] 非空字符(包括空格)
[:punct:] 标点符号
[:space:] 所有的空白字符(新行,空格,制表符)
[:upper:] 大写字符
[:xdigit:] 十六进制数字(0-9,a-f,A-F)
强烈注意:
在bash中,这代表是通配符,*用来代表任意(0或多个)字符。但是正则表达式并不是通配符,两者之间是不同的。正则中.代表绝对有一个任意字符的意思。
正则中
.(小数点): 代表一定有一个任意字符的意思;
*(星号):代表重复前一个0到无穷多次的意思。
bash中
*(星号):代表0个到无穷多个任意字符
? 代表一定有一个任意字符的意思。

2、awk:

参考:http://www.cnblogs.com/ggjucheng/archive/2013/01/13/2858470.html
强大的文本分析工具
 相比grep的查找、sed的编辑,awk其对数据的分析并生成报告时,显得更强大。
awk把文件逐行的读入,以空格为默认分割符将每行切片,切开的每部分再进行各种分析处理。
awk有三个不同的版本:awk、nawk和gawk。
使用方法:
awk ‘{pattern + action }’ { filename }
awk语言的最基本功能就是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作,完整的awk脚本通常用来格式化文本文件中的信息。
通常,awk是以文件中的一行为处理单位的,awk每接收文件的一行,然后执行相应的命令,来处理文本。
有3种方式调用awk:
1.命令行方式
awk [ -F field-separator] ‘commands’ input-file(s)
commands是真正的awk命令 -F 域分割符
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格
2.shell脚本方式
将所有的awk命令插入到一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。相当于shell脚本的首行:#!/bin/sh
可以换为#!/bin/awk
3.将所有的awk命令插入到一个单独文件,然后调用:
awk -f awk-script-file input-file(s)
重点介绍命令行:
工作流程:
awk读入有’\n’换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0 表示第0个域,$1则表示第一个域,$n表示第n个域.

例如:搜索/etc/passwd有root关键字的所有行
awk -F : ‘/root/’ /etc/passwd 如果没有action,默认是print每行的内容
awk -F : ‘/root/{ print $7}’ /etc/passwd 这里就指定了action { print \$7}
awk内置变量
ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk浏览的文件名
NR 浏览文件的记录数,这是第几行
FS 设置输入域分隔符,等价于命令行 -F 选项
NF 浏览记录的域的个数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符
awk中同时提供了print和printf两种打印输出的函数。
其中print函数的参数可以是变量,数值或字符串。字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就串联在一起而无法区分。
printf函数,其用法和c语言中的printf函数基本相似,可以格式化字符串,输出复杂时,printf更加好用,代码更容易懂。
awk编程编程
awk还可以自己定义变量。
awk ‘{count++;print $0;} END{print “user count is “,count}’ /etc/passwd
awk条件语句,从C语言中借鉴来的:
if(experssion)
{
statement;

}
也有循环,有数组
awk的注意事项:
所有的awk的动作,即在{}内的动作,如果有需要多个命令辅助时,可利用分号”;”间隔,或者直接以[Enter]按键来隔开每个命令;
逻辑运算当中,如果是“等于”的情况,则务必使用2个等号”==”;
格式化输出时,在printf的格式设置中,加上\n,才能进行分行!
与bash、shell的变量不同,在awk当中,变量可以直接使用,不用加$符号

sed命令

参考:https://www.cnblogs.com/ggjucheng/archive/2013/01/13/2856901.html
一种在线编辑器,一次处理一行内容。
处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”。
接着用sed命令处理缓冲区中的内容 ,处理完成后,把缓冲区中的内容送往屏幕,接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。
sed使用参数
-n 使用安静模式,只有经过特殊处理的那一行才会被列出来
-e 直接在命令列上进行sed的动作编辑
-f 直接将sed的动作写在一个文件内,-f filename 则可以运行filename内的sed动作。
-r:sed的动作支持的是延伸型正规表示法的语法。
-i: 直接修改读取的文件内容,而不是输出到终端
动作说明 [n1[,n2]] function
n1,n2 不见得会存在,一般代表[选择进行动作的行数]。
function:
a: 新增 a的后面可以接子串,而这些子串会在新的一行出现(目前的下一行)
c:取代 c的后面可以接子串,这些子串可以取代n1,n2之间的行
d:删除 后不接
i 插入 i的后面可以接字串。 可以直接修改文件内容,慎用。
p : 打印
s: 取代

举例:

nl /etc/passwd | sed ‘2,5d’ 将2-5行的内容删除
nl /etc/passwd | sed ‘2d’ 将第2行的内容删除
nl /etc/passwd | sed ‘3,$d’ 从第三行到最后删除
nl /etc/passwd | sed ‘2i drink tea ’ 第二行前面插入drink tea
nl /etc/passwd | sed ‘2,5c No 2-5 number’ 将2-5行的内容替换
nl /etc/passwd | sed -n ‘5,7p’ 仅仅显示5-7行
nl /etc/passwd | sed ‘/root/p’
sed ‘/s/要被取代的/新子串/g’

猜你喜欢

转载自blog.csdn.net/xiongluo0628/article/details/81571277