一、进程、线程和协程
1、进程
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。
2、线程
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。
3、协程
协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。
区别:
1、进程多与线程比较
线程是指进程内的一个执行单元,也是进程内的可调度实体。线程与进程的区别:
1) 地址空间:线程是进程内的一个执行单元,进程内至少有一个线程,它们共享进程的地址空间,而进程有自己独立的地址空间
2) 资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源
3) 线程是处理器调度的基本单位,但进程不是
4) 二者均可并发执行
5) 每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口,但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制
2、协程多与线程进行比较
1) 一个线程可以多个协程,一个进程也可以单独拥有多个协程,这样python中则能使用多核CPU。
2) 线程进程都是同步机制,而协程则是异步
3) 协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态
二、互斥锁
多个线程访问一个程序的时候经常会出现访问冲突的问题,所以我们引入互斥锁来解决(Mutex,Mutual Exclusive Lock),比如现在线程A,B在申请访问一个程序,但必须他们必须先有锁,所以他们先申请锁,如果A获得锁的线程可以完成“读--修改--写”的操作,然后释放锁给其他线程,而那些没有获得锁的线程,B只能等待而不能访问共享数据,这样“读--修改--写”三步操作组成一个原子操作,要么都执行,要么都不执行,不会执行到中期被打死,也不会在其他处理器上并行做这个操作。
例如:
from threading import Thread
from threading import Lock
num=0
def work1():
global num
for i in range(1000000):
mutex.acquire()
num+=1
mutex.release()
print('w1', num)
def work2():
global num
for i in range(1000000):
mutex.acquire()
num += 1
mutex.release()
print('w2',num)
mutex=Lock()
if __name__ == '__main__':
t1=Thread(target=work1)
t2= Thread(target=work2)
t1.start()
t2.start()
t1.join()
t2.join()
print(num)
当线程间运算次数过多的时候就会有同时调用全局变量的可能,也就会使程序丢失数据,添加锁会避免这种事情发生。
三、死锁
死锁有两种有两种情形:
一、如果同一个线程先后两次调用lock,在第二次调用时由于锁已经被占用,该线程会挂起等待别的线程释放锁,然而锁正是被自己占用着,该线程又被挂起而没有机会释放锁,所以它就永远停在等待状态,这叫做死锁。
二、线程A获得了锁1,线程B获得了锁2,这时线程A调用lock试图获得锁2,结果是需要挂起等待线程B释放锁2,而这时线程B也要调用lock试图获得锁1,结果是需要挂起等待线程A释放锁1,于是线程AB都永远处于挂起状态了
解决方法:
在程序中我们一般使用pthread_mutex_trylock来代替pthread_mutex_trylock避免死锁,或者使用一种稍微复杂一点的方法:如果线程需要多个锁时都按照相同的先后顺序获得锁。也可以选用银行家算法或者尽量减少资源的占用时间
形成死锁的原因是:
1,系统资源不足。
2,线程推进的顺序不当。
3,资源分配不当。
四、线程队列和生产者消费者模式
附上弹弹堂老玩家的中二代码:
from queue import Queue
#创建队列
q=Queue(2)
#方数据
q.put('极·轰天')
q.put('极·烈火')
print(q.full())#True
print(q.empty())#False
#取数据
q.get()
q.get()
print(q.empty())
优先级队列
from queue import PriorityQueue
#优先级队列包,继承了队列内容
p=PriorityQueue(4)
#任务不直接放入队列,需要封装到放入元组中(数值,消息)数值越小优先级越高
p.put((4,'極·雷霆'))
p.put((2,'極·轰天'))
p.put((3,'極·神风'))
p.put((1,'極·烈火'))
i=0
while i<p.qsize():
print(p.get())
from queue import LifoQueue
lq=LifoQueue()
lq.put('1')
lq.put('2')
print(lq.get())
from queue import Queue
from threading import Thread
import time
q=Queue(10)
wy=Queue(8)
def wuqibao(name):
count=1
while True:
v=q.put('%d k'%count)
print('%s生产了'%(name),'%d k'%count)
count+=1
time.sleep(0.5)
def jundui(name):
while True:
w=q.get()
print('%s买了'%(name),w)
time.sleep(10)
if __name__ == '__main__':
c=Thread(target=wuqibao,args=('\ntencent',))
c.start()
c = Thread(target=wuqibao, args=('\nwangyi',))
c.start()
g=Thread(target=jundui,args=('\n米国',))
g.start()
g=Thread(target=jundui,args=('\n日国',))
g.start()
五、排序
1、选择排序
list_1=[2,1,3,4,6,5,8,7,9]
for i in range(len(list_1)-1):
for j in range(len(list_1)-i):
if list_1[i]>list_1[i+j]:
list_1[i],list_1[j+i]=list_1[i+j],list_1[i]
print(list_1)
2、冒泡排序
print(list_1)
for i in range(len(list_1)-1):
for j in range(len(list_1)-i-1):
if list_1[j]>list_1[j+1]:
list_1[j+1],list_1[j]=list_1[j],list_1[j+1]
print(list_1)
3、归并排序
def merge_sort(alist):
n=len(alist)
mid=n//2
if n<=1:
return alist
left_list=merge_sort(alist[:mid])
right_list=merge_sort(alist[mid:])
left_pointer,right_pointer=0,0
result=[]
while left_pointer<len(left_list) and right_pointer<len(right_list):
if left_list[left_pointer]<right_list[right_pointer]:
result.append(left_list[left_pointer])
left_pointer+=1
else:
result.append(right_list[right_pointer])
right_pointer+=1
result+=left_list[left_pointer:]
result+=right_list[right_pointer:]
return result
if __name__ == '__main__':
list_1 = [2, 1, 3, 4, 6, 5, 8, 7, 9]
print(list_1)
x=merge_sort(list_1)
print(x)
六、查找算法
二分查找
list_01=list_1
list_01.sort()
first=0
last=len(list_01)-1
num=int(input("请输入要查找的数:"))
while first<=last:
mid=(first+last)//2
if num==list_01[mid]:
print('已找到')
break
elif num>list_01[mid]:
first=mid+1
elif num<list_01[mid]:
last=mid-1
else:
print('查无此数')