互斥锁、线程、GIL
作者:互联网
作业讲解
'''服务端'''
import socket
from multiprocessing import Process
def get_sever():
sever = socket.socket()
sever.bind(('127.0.0.1', 8080))
sever.listen(5)
return sever
def talk(sock):
while True:
data = sock.recv(1024)
print(data.decode('utf8'))
sock.send(data.upper())
if __name__ == '__main__':
# 方式一
# sever = socket.socket()
# sever.bind(('127.0.0.1', 8080))
# sever.listen(5)
sever = get_sever()
while True:
sock, addr = sever.accept()
p = Process(target=talk, args=(sock,))
p.start()
'''服务端'''
import socket
client = socket.socket()
client.connect(('127.0.0.1', 8080))
while True:
client.send(b'adsfaga')
data = client.recv(1024)
print(data.decode('utf8'))
互斥锁
一、作用
多个程序同时操作一份数据的时候很容易产生数据错乱,为了避免错乱,我们需要使用互斥锁
互斥锁能将并发变成串行,虽然牺牲了程序的执行效率倒是保证了数据安全
二、代码演示
from multiprocessing import Process, Lock
mutex = Lock()
mutex.acquire() # 抢锁
mutex.release() # 释放锁
三、强调
互斥锁只应该出现在多个程序操作数据的地方,其他位置尽量不用
ps:以后我们自己处理锁的情况很少,只需要指定锁的功能即可
线程理论
一、前提
进程:是资源单位
相当于是车间,进程负责给内部的线程提供相应的资源
线程:是执行单位
线程相当于是车间里的流水线,线程负责执行真正的功能
二、多进程和多线程的区别
多进程 | 多线程 |
---|---|
需要申请内存空间,需要拷贝全部代码,资源消耗大 | 不需要申请内存空间,也不需要拷贝全部代码,资源消耗小 |
三、特点
1.一个进程至少有一个线程
2.同一进程下多个线程之间资源共享
四、创建线程的两种方式
from threading import Thread
from multiprocessing import Process
import time
class MyThread(Thread):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
print(f'{self.name}正在运行')
time.sleep(3)
print(f'{self.name}运行结束')
obj = MyThread('abcd')
obj.start()
print('主线程')
# abcd正在运行
# 主线程
# abcd运行结束
五、多线程实现TCP服务端并发
比多进程更加简单方便,消耗的资源更少
六、join方法
1.作用
让主线程等到子线程运行结束之后再运行
2.代码演示
'''多线程'''
from threading import Thread
import time
def task():
print('子线程正在执行')
time.sleep(3)
print('子线程运行结束')
t = Thread(target=task)
t.start()
t.join()
print('主线程')
'''结果'''
# 子线程正在执行
# 子线程运行结束
# 主线程
七、同一个进程下的线程共享数据
一、代码演示
'''多线程'''
会改变主线程的数据
from threading import Thread
money = 1000
def func():
global money
money = 666
def func2():
global money
money = 888
t = Thread(target=func)
t.start()
t.join()
print(money) # 666
t2 = Thread(target=func2)
t2.start()
t2.join()
print(money) # 888
'''多进程'''
不会改变主进程的数据
from multiprocessing import Process
money = 10000
def func():
global money
money = 666
print('子进程1 money:', money) # 666
def func2():
global money
money = 888
print('子进程2 money:', money) # 888
if __name__ == '__main__':
p = Process(target=func)
p.start()
p.join()
print('主进程:', money) # 10000
if __name__ == '__main__':
p2 = Process(target=func2)
p2.start()
p2.join()
print('主进程:', money) # 10000
八、线程对象相关方法
1.进程号
同一个进程下开设多个线程拥有同样的进程号
2.线程号
from threading import Thread, current_thread
current_thread().name
主线程:MainThread 子线程:Thread-N
3.进程下的线程数
active_count()
九、守护线程
一、特点
守护线程随着被守护的线程的结束而结束
二、代码演示
from threading import Thread
import time
def task():
print('子线程运行task函数')
time.sleep(3)
print('子线程运行task结束')
t = Thread(target=task)
# t.daemon = True
t.start()
# t.daemon = True
print('主线程')
"""
进程下所有的非守护线程结束 主线程(主进程)才能真正结束!!!
"""
GIL全局解释器锁
一、储备知识
1.python解释器也是由编程语言写出来的
Cpython 用C写出来的 (最常用的)
Jpython 用Java写出来的
Pypython 用python写出来的
二、介绍
1.官方解释
In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.
2.详解
2.1.GIL的研究是Cpython解释器的特点,不是python语音的特点
2.2.GIL本质是一把互斥锁
2.3.GIL的存在使得同一个进程下的多个线程无法同时执行
言外之意:单进程下的多线程无法利用多核优势,效率低!!
2.4.GIL的存在主要是因为:Cpython解释器中垃圾回收机制不是线程安全的
3.误解
3.1.误解:python的多线程就是垃圾 利用不到多核优势
不对
python的多线程确实无法使用多核优势 但是在IO密集型的任务下是有用的
3.2.误解:既然有GIL 那么以后我们写代码都不需要加互斥锁
不对
GIL只确保解释器层面数据不会错乱(垃圾回收机制)
针对程序中自己的数据应该自己加锁处理
3.3.所有的解释型编程语言都没办法做到同一个进程下多个线程同时执行
考试总结
1.基本上走下来没多大问题
2.打的太慢
3.打代码的过程中有许多小问题,还应该多打多练
标签:__,money,互斥,线程,print,import,GIL,进程 来源: https://www.cnblogs.com/Zhang614/p/16574218.html