python之多线程

1.一个进程中可以有多个线程,进程是指在内存中开辟出一块空间,线程主要做一些耗时操作。一个进程中的多个线程共享该进程的资源是指cpu调用该进程中的某一个线程,然后该线程可以用该进程的资源,并不是多个线程同时用该进程的资源。

2.线程:Threading

(1)状态:新建对象—start—就绪——cpu调用运行——结束,当sleep时,该线程从cpu中退出,此时称为阻塞状态,当sleep时间结束时,该线程回到就绪状态,等待cpu的调用执行。

(2)线程是可以共享全局变量的

(3)GIL 全局解释器锁

(4)线程同步:当共享数据时,需要给线程加锁,一个线程执行它的任务前,需要先获取一把锁(lock),当执行完任务,该线程就释放锁,然后下一个线程才能被cpu调用运行。缺点:速度慢

(5)python底层只要用线程默认加锁,当cpu运算量达到某值时锁会自动释放。

3.进程:计算密集型

线程:耗时操作:爬虫、读写(IO)

4.多线程同步

# 多线程
import threading
import random
import time

lock = threading.Lock()

list1 = [0] * 10


def task1():
    # 获取线程锁,如果已经上锁,则等待锁的释放
    lock.acquire()  # 阻塞
    for i in range(len(list1)):
        list1[i] = 1
        time.sleep(0.5)
    lock.release()


def task2():
    lock.acquire()  # 阻塞
    for i in range(len(list1)):
        print('---->', list1[i])
        time.sleep(0.5)
    lock.release()


if __name__ == "__main__":
    t1 = threading.Thread(target=task1)
    t2 = threading.Thread(target=task2)

    t2.start()
    t1.start()

    t2.join()
    t1.join()

    print(list1)

输出结果:

5.死锁:存在两把及以上的锁,两个线程间相互制约

# 死锁
from threading import Thread, Lock
import time

lockA = Lock()
lockB = Lock()


class MyThread(Thread):
    def run(self):  # start()
        if lockA.acquire():  # 如果可以获取到锁则返回True
            print('self.name' + '获取了A锁')
            time.sleep(0.1)
            if lockB.acquire():
                print('self.name' + '又获取了B锁,原来还有A锁')
                lockB.release()
            lockA.release()


class MyThread1(Thread):
    def run(self):  # start()
        if lockB.acquire():  # 如果可以获取到锁则返回True
            print('self.name' + '获取了B锁')
            time.sleep(0.1)
            if lockA.acquire():
                print('self.name' + '又获取了A锁,原来还有B锁')
                lockA.release()
            lockB.release()


if __name__ == "__main__":
    t1 = MyThread()
    t2 = MyThread1()

    t1.start()
    t2.start()

输出结果:,然后一直处于等待状态。

解决死锁的方式:(1)重构代码

(2)在lock.acquire()中添加参数timeout

6.两个线程间通信:生产者和消费者

python的queue模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列PriorityQueue。这些队列都实现了锁原理(可以理解为原子操作,即要么不做,要么就做完),能够在多线程中直接使用。

注意:当两个线程同时就绪时,cpu选择调用哪个线程执行是随机的,没有顺序。

# 线程间通信
import queue
import threading
import time
import random


def produce(q):
    i = 0
    while i < 10:
        num = random.randint(1, 100)
        q.put("生产者产生数据:%d" % num)
        print("生产者产生数据:%d" % num)
        time.sleep(1)
        i += 1
    q.put(None)
    # 完成任务
    q.task_done()


def consume(q):
    while True:
        item = q.get()
        if item is None:
            break
        print("消费者获取到:%s" % item)
        time.sleep(4)
    # 完成任务
    q.task_done()


if __name__ == '__main__':
    q = queue.Queue(10)
    arr = []

    # 创建生产者
    th = threading.Thread(target=produce, args=(q,))
    th.start()

    # 创建消费者
    tc = threading.Thread(target=consume, args=(q,))
    tc.start()

    th.join()
    tc.join()
    print("over!")

输出结果:

7.自定义线程:线程对象调用方法start(),然后start()方法会执行run()方法

class MyThread(Thread):
    def __init__(self,name):
        super().__init__()
        self.name = name
    
    def run(self):
        任务
                
t = MyThread('name')
t.start()

8.数据共享:进程共享数据和线程共享数据区别:

进程是每个进程中都有一份

线程是共同用一个数据,就会导致数据安全性问题,然后就要用到GIL———>伪线程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值