Python 多线程

一. 创建并执行线程

1. threading.Thead直接创建

用Thread(target=函数名)创建线程对象,用start根据线程对象创建线程并执行。

import threading
from threading import Thread

def hello():
    print("hello world")
    import time
    time.sleep(1)

if __name__ == "__main__":
    # 创建线程对象
    t = Thread(target=hello)
    # 执行线程
    t.start()
    # 查看所有的线程
    print(threading.enumerate())

结果;

hello world
[<_MainThread(MainThread, started 4640308672)>, <Thread(Thread-1, started 123145556144128)>]

2. 继承Thread并覆盖run方法

import threading
from threading import Thread

class HelloThread(Thread):

    def run(self):
        print("hello world")
        import time
        time.sleep(1)

if __name__ == "__main__":
    # 创建线程对象
    t = HelloThread()
    # 执行线程
    t.start()
    # 查看所有的线程
    print(threading.enumerate())

结果:

hello world
[<_MainThread(MainThread, started 4657499584)>, <HelloThread(Thread-1, started 123145479835648)>]

二. 多线程共享全局变量

多线程中的变量共享与单线程的变量共享在直觉上相同。

多线程是共享全局变量的

from threading import Thread

NUM = 1

def add_num():
    global NUM
    NUM += 1
    print("NUM in add_num is ", NUM)


def print_num():
    print("NUM in print_num is ", NUM)


if __name__ == "__main__":
    t1 = Thread(target=add_num)
    t2 = Thread(target=print_num)

    t1.start()
    # 主线程等待t1执行完毕
    t1.join()

    t2.start()
    
    print("NUM in main is ", NUM)

结果

NUM in add_num is  2
NUM in print_num is  2
NUM in main is  2

局部作用域

from threading import Thread

def add_num(number):
    number += 1
    print("NUM in add_num is ", number)


def append_3(list_):
    list_.append(3)
    print("list in append_3 is ", list_)


def print_num(number):
    print("NUM in print_num is ", number)


def print_list(list_):
    print("list in print_list is ", list_)


if __name__ == "__main__":

    def start_and_join(t):
        t.start()
        t.join()

    # 测试传入可变类型
    a_list = [1, 2]
    t_list = Thread(target=append_3, args=(a_list, ))
    t_print_list = Thread(target=print_list, args=(a_list, ))

    start_and_join(t_list)
    start_and_join(t_print_list)
    print("list in main is ", a_list)
    print()

    # 测试传入变量不可变类型
    a_number = 10
    t_number = Thread(target=add_num, args=(a_number, ))
    t_print_number = Thread(target=print_num, args=(a_number, ))

    start_and_join(t_number)
    start_and_join(t_print_number)
    print("number in main is ", a_number)

共享全局变量的问题 - 资源竞争

from threading import Thread

NUMBER = 0
LOOP = 10 ** 6

def add_number1():
    global NUMBER
    for i in range(LOOP):
        NUMBER += 1
    print("number in add_num1 is ", NUMBER)


def add_number2():
    global NUMBER
    for i in range(LOOP):
        NUMBER += 1 
    print("number in add_num2 is ", NUMBER)


if __name__ == "__main__":
    t1 = Thread(target=add_number1)
    t2 = Thread(target=add_number2)

    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print("number in main is ", NUMBER)

结果

number in add_num1 is  1331562
number in add_num2 is  1336960
number in main is  1336960

使用互斥锁解决资源竞争的问题

互斥锁

  • 创建:mutex = threading.Lock()
  • 锁定:mutex.acquire()
  • 释放:mutex.release()
from threading import Thread, Lock

NUMBER = 0
LOOP = 10 ** 6
mutex = Lock()

def add_number1():
    global NUMBER
    for i in range(LOOP):
        mutex.acquire()
        NUMBER += 1
        mutex.release()
    print("number in add_num1 is ", NUMBER)


def add_number2():
    global NUMBER
    for i in range(LOOP):
        mutex.acquire()
        NUMBER += 1 
        mutex.release()
    print("number in add_num2 is ", NUMBER)


if __name__ == "__main__":
    t1 = Thread(target=add_number1)
    t2 = Thread(target=add_number2)

    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print("number in main is ", NUMBER)

死锁

当有多个锁时,两方互相等待锁释放,这时就会产生死锁。

避免死锁的方法:

  • 银行家算法,在程序设计时避免死锁
  • 添加超时等待时间
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值