Day41 并发编程之线程

Day41 并发编程之线程

1、互斥锁

多个程序同时操作一份数据的时候很容易产生数据错乱!
为了避免数据错乱,我们要使用互斥锁

互斥锁
将并发变成串行 虽然牺牲了程序的执行效率 但是保证了数据安全

如何使用

#互斥锁 也是multiprocessing 模块中的类 我们可以在创建进程倒模块时一起倒入
from multiprocessing import Process,Lock
mutex = Lock()
#抢锁
mutex.acquire()
#释放锁
mutex.release()

注意
互斥锁只应该出现在多个程序操作数据的地方 其他位置尽量不要加

2、线程

线程是资源单位
进程相当于是车间 进程负责给颞部的线程提供相应的资源

线程是执行单位
线程相当于是车间里面的流水线 线程负责执行真正的功能

一个进程至少含有一个

多进程与多线程的区别
多进程
需要申请内存空间 需要拷贝全部代码 资源消耗大

多线程
不需要申请内存空间 也不需要拷贝全部代码 资源消耗小

同一个进程下多个线程之间资源共享

2.1、创建线程的两种方式

开设线程不要完整的拷贝代码 所以无论什么系统都不会出现反复操作的情况 也不需要在启动脚本执行 但是为了兼容性和统一性 习惯在启动脚本编写

线程的创建 与进程创建 代码步骤相似
方式一:

from threading import Thread
import time

#方法一
def task(name):
    print(f'{name}正在运行')
    time.sleep(3)
    print(f'{name}运行结束')


if __name__ == '__main__':
    #创建线程对象
    t = Thread(target=task, args=('kk',))
    t.start()
    print('主线程')

方式二

import time
from threading import Thread


class My_Thread(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= My_Thread('jason')
obj.start()
print('主线程')

3、多线程实现TCP服务端并发

比进程更加简单方便 消耗的资源更少

server

import socket
from threading import Thread

def get_server():
    server = socket.socket()
    server.bind(('127.0.0.1', 8080))
    server.listen(5)
    return server


def talk(sock):
    while True:
        data = sock.recv(1024)
        print(data.decode('utf8'))
        sock.send(data.upper())




if __name__ == '__main__':
    server = get_server()
    while True:
        sock, addr = server.accept()
        # 开设进程去完成数据交互
        t = Thread(target=talk, args=(sock,))
        t.start()

client

mport socket


client = socket.socket()
client.connect(('127.0.0.1', 8080))


for i in range(1000000):
    client.send(b'hello baby')
    data = client.recv(1024)
    print(data.decode('utf8'))

4、join方法

主线程等到子线程运行结束之后再运行

from threading import Thread
import time

def task():
    print('正在执行')
    time.sleep(3)
    print('运行结束')

t=Thread(target=task)
t.start()
t.join()
print('主线程')

5、同一进程下线程之间数据共享

from threading import Thread

money = 1000


def func():
    global money
    money = 888


if __name__ == '__main__':
    t = Thread(target=func)
    t.start()
    # 确保线程运行完毕 再查找 money 结果更具有说服性
    t.join()
    print(money)

6、线程对象相关方法

进程号
同一个进程下开设的多个线程拥有相同的进程号
查看线程名、线程号

from threading import Thread,current_thread
import os
#查看主线程
print(current_thread().name)
#查看线程号
print(os.getpid())

def task(name):
    print(f'{name}正在运行')
    #查看子线程
    print(current_thread().name)
    #查看子线程号
    print(os.getpid())
    time.sleep(3)
    print(f'{name}运行结束')

:MainThread	子:Thread-N

统计线程数

from threading import active_count()

7、守护线程

守护线程伴随着被守护的线程的结束而结束
子线程守护主线程 伴随主线程结束 而结束

进程下所有的非守护线程结束 主线程(主进程)才能结束

from threading import Thread
import time

def task():
    print('子线程运行task函数')
    time.sleep(3)
    print('子线程运行task结束')


t = Thread(target=task)
#t线程为守护线程
# t.daemon = True
t.start()
#不能写下面
# t.daemon = True
print('主线程')

8、GIL全局解释器

储备知识
python解释器也是由编程语言写出来的
Cpython 用c写出来的
Jpython 用Jave写的
Pypython 用python写出来的

最常用的就是C python(默认)

官方文档GIL的解释

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.)

  1. GIL的研究是Cpython解释器的的特点 不是python语言的特点

  2. GIL本质也是一把互斥锁

  3. GIL的存在使得同一进程下的多个线程无法同时执行(关键)
    言外之意:单进程下的多线程无法利用多核优势 效率低!!

  4. GIL的存在主要是因为Cpython解释器中垃圾回收机制不是线程安全的

  5. 误解: python的线程是垃圾 利用不到多核优势
    python的线程确实无法使用多核优势 但是在IO密集型的任务下是有用的

  6. **误解:**既然有GIL 那么以后我们写代码都不需要加互斥锁
    不对 GIL只确保解释器层面数据 不会错乱(垃圾回收机制)
    针对 程序中自己的数据应该自己加锁处理

  7. 所有的解释器型编程语言 都没办法做倒同一个进程下多个线程同时执行
    我们平时在写代码的时候 不需要考虑GIL 只在学习和面试阶段才考虑

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值