计算机只认识二进制
计算机语言:
1)机器语言----二进制
2)汇编语言----直接操作寄存器,计数器等硬件
3)高级语言—C/C++/java/php/等
Python解释器:GIL是一个排它锁
Python优点:开发简单,高效,因为拥有更多的第三方库
Python缺点:效率差,因为Python中的多线程是伪多线程。
什么时候用多线程,什么时候用多进程?
计算密集的场景用多进程,对于IO密集型的用多线程。
进程,线程,协程,他们的区别和联系:
进程:,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。
线程:线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.
查看线程的数量:threading.enumerate()
多线程的执行顺序是不确定的。
当前状态执行到sleep语句时,线程进入阻塞(Blocked)
到sleep后,线程进入就绪(Runnable),等待调度
调度
新建------就绪-------运行-------死亡
阻塞
多进程内存相互独立,不能共享全局变量 如果通信就得用Queue
多线程可以共享全局变量
优点 多线程之间数据相互交换变得简单蛮方便
缺点 线程可以对全局变量造成改变,数据不安全
协程:—微线程,比线程更小的调度单位。协程是一个单独的执行单元,自带CPU上下文。
协程的实现方法:(1)yield, (2)greenlet
def fbnq(n):
i=0
a,b=0,1
while i<n:
yield b
a, b = b, a + b
i+=1
x=fbnq(12)
print(next(x))
print(next(x))
线程与进程的区别:
1)进程是系统进行资源分配和调度的一个基本单位,线程是进程的一个实体,是CPU调度和分配的基本单位。线程是比进程更小的能独立运行的基本单位。
2)线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如:程序的计数器,栈等),它可以与同一进程当中的其他线程共享进程所拥有的全部资源。
联系:
1)一个程序至少有一个进程,一个进程至少有一个线程。
2)线程是划分尺度较小的进程(资源比进程占用的少),使得多线程程序并发性高。
3)进程在执行过程中拥有独立的内存单元,而多个线程共享这块内存空间,从而大大提高了程序的运行效率。
4)线程不能独立执行,必须依存在进程中。
什么是线程锁,什么是死锁,死锁产生的原因以及解决死锁的办法。
缺点 线程可以对全局变量造成改变,数据不安全
解决方案:
加锁:互斥锁
当多线程几乎同时修改某一个共享参数时就需要同步控制
锁的状态:锁定/非锁定
在threading模块下面有一个Lock类,可以方便的锁定使用
1创建
mutex=Lock()
2锁定
Mutex.acquire([blocking])
3解锁
Mutex.release()
Blocking默认为True则线程阻塞,知道获取到这个锁为止
锁将并行操作变为串行操作
from threading import Thread
from threading import Lock
gum=0
def wrike1():
global gum
for i in range(1000000):
mutex.acquire()
gum+=1
mutex.release()
def wrike2():
global gum
for i in range(1000000):
mutex.acquire()
gum+=1
mutex.release()
mutex=Lock()
if __name__ == '__main__':
t1=Thread(target=wrike1)
t2=Thread(target=wrike2)
t1.start()
t2.start()
t1.join()
t2.join()
print(gum)
总结 锁的好处:
1 确保了某段关键代码只能由一个线程从头到尾的完成的执行
2 阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行
3 由于可以存在多个锁,不同的线程持有有不同的锁,并试图获取对方持有的锁时,可能会造成死锁。
死锁:
例子: 两个线程(线程1是你,线程2是老婆),做菜
资源:锅,馋
抄两个菜,你们两个各炒一个
解决方法
1尽量减少资源占用时间,可以降低死锁的发生的概率
2资源的访问要有序,
3银行家算法:优先满足占用资源较小的任务。
生产者与消费者,队列!
消息队列
导入模块
from mulitprocessing import Queue
代码:
from multiprocessing import Queue
q=Queue()
q.put(‘1’)
q.put(‘2’)
value=q.get()
print(value)
应用到多进程中:
from multiprocessing import Queue
from multiprocessing import Process
import random
import time
def write(q):
for value in ['A','B','C','D','Exit']:
q.put(value)
print('我写入了%s'%(value))
time.sleep(random.random())
def read(q):
print('我要读了')
while True:
if not q.empty():
value=q.get()
if value=='Exit':
break
else:
print('我读取了%s'%(value))
time.sleep(random.random())
if __name__ == '__main__':
q=Queue()
p1=Process(target=write,args=(q,))
p2=Process(target=read,args=(q,))
p1.start()
p2.start()
线程队列:
导入模块
from queue import Queue
1 FIFO----------默认队列 Frist Input First Output先进先出
2 LIFO---- ----------Last ------------------------------------------后进先出
3 PriorityQueue-----优先级队列
四 使用:
from queue import Queue
q=Queue()#默认先进先出
from queue import Queue#先进先出队列
from queue import PriorityQueue#优先级队列,继承了Queue
from queue import LifoQueue#后进先出队列
#任务不要直接加进去,需要封装到元组当中。
#格式:(数字,消息)数字越小,优先级越高
pq.put((1,‘文件1’))
pq.put((0,‘文件2’))
pq.put((-11,‘文件3’))
print(pq.get())
一,生产者与消费者:主要目的是为了提高效率。
定义: 在并发编程中使用生产者与消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据速度。
案例:厨师做包子,顾客吃包子。
from queue import Queue
from threading import Thread
import time
q=Queue(maxsize=10)
def cooker(name):
count=1
while True:
q.put('包子%d'%(count))
print('%s生产了%s'%(name,count))
count+=1
time.sleep(0.5)
def customer(name):
while True:
print('%s吃了%s'%(name,q.get()))
time.sleep(0.5)
if __name__ == '__main__':
t1=Thread(target=cooker,args=('刘大厨',))
t1.start()
t2=Thread(target=customer,args=('张三',))
t2.start()
二分查找(折半查找)
1,二分查找的前提是有序:
例如 a=[3,2,5,7,5,4,7,4,2,1]
先排序:
先拿出列表中的那个元素mid,和输入的num进行比较。
如果num大于mid, 表明num在mid—end里面
如果num小于mid, 表明num在num—mid里面
二分查找:
先排序
a=[3,2,5,7,5,4,7,4,2,1]
num=int(input('请输入一个数:'))
a.sort()
first=0
end=len(a)-1
while first<=end:
mid=(first+end)//2
if a[mid]==num:
print('找到了')
break
elif a[mid]>num:
end=mid-1
elif a[mid]<num:
first=mid+1
else:
print('没找到')
冒泡排序
a=[7,6,3,5,2,1,5,9]
ysgs=len(a)
for i in range(0,ysgs):
for j in range(0,ysgs-1-i):
if a[j]>a[j+1]:
a[j],a[j+1]=a[j+1],a[j]
print(a)
树和二叉树
计算机当中的树一般是指 倒悬树
例如 计算机当中的文件夹管理
树
二叉树的性质:
1)第i层上,节点数为2的i-1次方个
2)深度为K的二叉树至多有2的次方减1个节点。例如:本图的节点为 222*2-1=7个节点
如果7是整个树的节点数的个数,那么这棵树就是‘’
树的度,节点的度,有几个分支,就是几度。
3)对任何一棵二叉树,若其叶子节点数为n0,度为2的节点数为n2,则n0=n2+1.
例如上图: n0=4 n2=3 则 n0=n2+1
二叉树的遍历
—DLR---------先根序遍历
—LDR---------中根序遍历
—LRD---------后根序遍历
遍历过长中,深度优先和广度优先很重要
栈的应用:
1)中缀表达式转换成后缀表达式:
2)后缀表达式的计算:
E.g.中缀表达式:1+2*3/4
后缀表达式:操作数在前,操作符
内存:堆儿和栈
由于硬盘速度太慢,远远供应不上CPU执行的速度。
栈:受限的线程表
受限:单端开口
特点:先后出
静态栈:
容量事先已经定义好,后期不能改变。 如果多放会溢出。
递归:递归深度不能太深,如果太深可能会导致栈溢出。
def s(n):
if n==1:
return 1
result=n+s(n-1)
return result
if __name__ == '__main__':
result=s(10)
print('累加和:',result)