进程与线程相关

查看进程号

from multiprocessing import Process,current_process
import os

current_process().pid #查看当前进程号
os.getpid()  #查看当前进程号
os.getppid()  #查看当前进程的父进程号

僵尸进程与孤儿进程

'''
僵尸进程:进程结束后不会立即释放占用的资源(PID),会保留一段时间供父进程查看
孤儿进程:子进程存活,父进程意外死亡,孤儿进程操作系统会自动回收相应的资源
'''

守护进程

'''
被守护进程结束后守护进程也立即跟着结束
'''
#如何开启 在start语句之前写一下代码
p.daemon=True
p.start()

互斥锁

'''
多个人在操作同一份数据的时候会出现数据错乱问题
针对上述问题我们通常都是加锁处理

作用:
将并发变成串行,牺牲了程度的运行效率但是保证了数据的安全

注意:
	只在操作数据的部分加锁即可
	锁尽量不要着急去处理,容易造成死锁现象
'''
from multiprocessing import Lock
mutex=Lock()
#抢锁
mutex.acquire()
#释放锁
mutex.release()

#模拟抢票

队列Queue

'''
队列:先进先出
堆栈:先进后出
'''
from multiprocessing import Queue
q=Queue() #括号内可以放数字来限制队列的大小
q.put()  #放数据
q.get() #取数据

q.full()  #判断队列是否满了
q.empty()  #判断队列是否空了
q.get_nowait()  #取数据的时候如果没有数据直接报错
q.get(timeout=3)  #取数据的时候如果没有数据等3秒,还没有则直接报错

进程间通信

'''
进程间无法直接进行数据交互,但是可以通过队列或者管道实现数据交互
管道:
队列:管道+锁

本地测试是才会用到Queue,实际生产则用别人封装好的功能
redis
kafka
RQ
'''

生产者与消费者模型

'''
生产者+消费队列+消费者
为何要有消息队列的存在:是为了解决供销不平衡的问题

#JoinableQueue
可以被等待的q
你在我往队列中放数据的时候,内部会有一个计数器自动加1
你在从队列中取数据的时候,调用task_done()内部计时器自动减1
q.join()当计数器为0是才继续往下执行
'''

线程理论

'''
进程:资源单位
线程:执行单位
线程才是真正干活的人,干活的过程中需要的资源由所在的进程提供

每一个进程都自带一个线程

同一个进程内可以创建多个线程

开进程
	申请内存空间
	“拷贝代码”
	消耗资源较大
	
开线程
	同一个进程内创建多个线程,无需上述两部操作,消耗资源相对较小
'''

开启进程的两种方式

# 方式一
from multiprocessing import Process
from threading import Thread
import time
def task(name):
    print('%s is running'%(name))
    time.sleep(2)
    print('%s is over'%(name))
if __name__ == '__main__':

    t=Thread(target=task,args=('lz',))
    t.start()
    # p = Process(target=task,args=('lz1',))
    # p.start()
    print('主')


#方式二
from threading import Thread
import time
class MyThread(Thread):
    def __init__(self,name):
        #重写了别人的方法,有不知道别人的方法有什么
        super().__init__()
        self.name=name
    def run(self) :
        print('%s is running'%(self.name))
        time.sleep(1)
        print('%s is over'%(self.name))
if __name__ == '__main__':
    t=MyThread('lz')
    t.start()
    print('主')

TCP服务端实现并发的效果

import socket
from threading import Thread
from multiprocessing import Process
'''
服务端
    1、要有固定的IP和PORT
    2、不间断提供服务
    3、能够支持并发
'''
server=socket.socket()#括号内不加参数默认就是tcp协议
server.bind(('127.0.0.1',8081))
server.listen(5)
def task(conn):
    while True:
        try:
            data=conn.recv(1024)
            if len(data)==0:break
            print(data.decode('utf-8'))
            conn.send(data.upper())
        except Exception as e:
            print(e)
            break
    conn.close()

while True:
    conn,addr=server.accept()
    #通信循环
    t=Thread(target=task,args=(conn,))
    t.start()


    
    '''
    客户端
    '''
import socket
client=socket.socket()
client.connect(('127.0.0.1',8081))
while True:
    data=input('>>>>:').strip()
    client.send(data.encode('utf-8'))
    data1=client.recv(1024)
    print(data1.decode('utf-8'))

进程对象的join方法

from threading import Thread
import time
def task(name):
    print('%s is running'%(name))
    time.sleep(1)
    print('%s is over'%(name))
if __name__ == '__main__':
    t = Thread(target=task,args=('lz',))
    t.start()
    t.join()  #主进程等待子进程运行结束再执行
    print('主')

同一个进程下多个线程的数据共享

from threading import Thread
# from multiprocessing import Process
import time
money=100
def task():
    global money
    money=666
if __name__ == '__main__':
    t= Thread(target=task)
    # p = Process(target=task)
    # p.start()
    t.start()
    print(money)

线程对象属性及其他方法

from threading import Thread,active_count,current_thread
import os,time
def task(n):
    print('hello world',current_thread().name)
    time.sleep(n)
if __name__ == '__main__':
    t = Thread(target=task,args=(1,))
    t1 = Thread(target=task,args=(2,))
    t.start()
    t1.start()
    t1.join()
    print('主',active_count())  #统计当前正在活跃的线程数
    # print('主',os.getpid())
    # print('主',current_thread().name)  #获取线程名字

守护线程

from threading import Thread
import time


def task(name):
    print('%s is running' % (name))
    time.sleep(1)
    print('%s is over' % (name))


if __name__ == '__main__':
    t = Thread(target=task, args=('lz',))
    t.daemon = True
    t.start()
    print('主')

线程互斥锁

from threading import Thread,Lock
import time

money = 100
mutex=Lock()

def task():
    global money
    mutex.acquire()
    tmp = money
    time.sleep(0.1)
    money = tmp - 1
    mutex.release()


if __name__ == '__main__':

    t_list = []
    for i in range(100):
        t = Thread(target=task)
        t.start()
        t_list.append(t)
    for t in t_list:
        t.join()
    print(money)

GIL全局解释器锁

'''
重点:
	1、GIL不是python的特点而是CPython解释器的特点
	2、GIL是保证解释器级别的数据的安全
	3、GIL会导致同一个进程下的多个线程无法同时执行即无法利用多核优势
	4、针对不同的数据还是需要加不同的锁处理
	5、解释型语言的通病:同一个进程下多个线程无法利用多核优势
	
'''

GIL与普通互斥锁的区别

from threading import Thread,Lock
import time

money = 100
mutex=Lock()

def task():
    global money
    mutex.acquire()
    tmp = money
    time.sleep(0.1)
    money = tmp - 1
    mutex.release()


if __name__ == '__main__':

    t_list = []
    for i in range(100):
        t = Thread(target=task)
        t.start()
        t_list.append(t)
    for t in t_list:
        t.join()
    print(money)

同一个进程下的多线程无法利用多核优势

#计算密集型
# from multiprocessing import Process
# from threading import Thread
# import os,time
# def work():
#     res = 0
#     for i in range(1000000):
#         res *= i
#
# if __name__ == '__main__':
#     l = []
#     print(os.cpu_count())
#     start_time=time.time()
#     for i in range(8):
#         p = Process(target=work)
#         t = Thread(target=work)
#         t.start()
#         # p.start()
#         l.append(t)
#     for p in l:
#         p.join()
#     print(time.time()-start_time)  #0.9109606742858887



#IO密集型
from multiprocessing import Process
from threading import Thread
import os,time
def work():
    time.sleep(2)
if __name__ == '__main__':
    l = []
    print(os.cpu_count())
    start_time=time.time()
    for i in range(40):
        p = Process(target=work)  #4.8199303150177
        t = Thread(target=work)  #2.01092791557312
        t.start()
        # p.start()
        # l.append(p)
        l.append(t)
    for p in l:
        p.join()
    print(time.time()-start_time)
'''
总结:
多进程和多线程都各有各自的优势
通常用多进程下开设多线程
'''
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值