python多线程

python 多线程

每个程序运行一般会包含多个线程,对于python而言,它的多线程一般都是对于IO密集型程序较为有效,因为其存在全局解释器锁GIL,所谓的全局解释器锁,也就是只允许主循环中只有一个线程在运行。但对于计算密集型的程序python的多线程就没有什么意义了。
全局解释器锁的应用主要是为了保证数据安全,不出差错。当多个线程同时对一个数据访问时,就会出错。比如我们用50个线程向同一个账户存入1块钱时。当不使用锁时。

import time
from threading import Thread

def show_time(func):  # 设置一个修饰器
    def wrapper(*args, **kwargs):
        start = time.time()
        func(*args, **kwargs)
        end = time.time()
        print(f'程序运行耗费时间{end - start}')

    return wrapper


class Account():

    def __init__(self):
        self.all_money = 0

    @property
    def show_money(self):
        return self.all_money

    def add_money(self, deposite_money):
        all_money = deposite_money + self.all_money  # 此处重点 当你把此处改为self.all_money += deposite_money 是返回的数据其实还是安全的
        #正是因为此处导致结果偏差,此时线程是不安全的
        time.sleep(0.01)
        self.all_money = all_money

class Deposite_Money(Thread):

    def __init__(self, acount, deposite_money):
        super().__init__()
        self.acount = acount
        self.deposite_money = deposite_money


    def run(self):
        self.acount.add_money(self.deposite_money)


@show_time
def main():
    threads = []
    my_acount = Account()
    for i in range(50):
        a = Deposite_Money(my_acount, 1)
        threads.append(a)
        a.start()
    for thread in threads:
        thread.join()
    print(f'账户余额总数为{my_acount.show_money}')


if __name__ == '__main__':
    main()

                  
          

以下的代码是使用锁之后的

from threading import Thread, Lock
import time


def show_time(func):   # 创建一个修饰器显示程序运行时间
      def wrapper(*args, **kwargs):
            start = time.time()
            func(*args, **kwargs) 
            end = time.time()
            print(f'程序运行耗费{end - start}秒')
      return wrapper   
         
class Account():
"""
加锁类
这种类一般会用在线程类上
"""
    def __init__(self):
        self.all_money = 0
        self.lock = Lock()

    @property   # 修饰器 保护all_money数据,对外只显示show_money接口
    def show_money(self):
        return self.all_money

    def add_money(self, deposite_money):  # 此时的deposite_money没有初始化,需要外部导入
        self.lock.acquire()  # 加上线程锁
        try:
            self.all_money += deposite_money
            time.sleep(0.05)
        finally:
            self.lock.release()  # 解锁


class Deposit_Money(Thread):
    """
    创建一个线程类
    先是初始化__init__()
    接着使用run()完成相关操作
    """
    def __init__(self, acount, deposite_money):
        super().__init__()
        self.acount = acount   # 直接导入一个类的实例
        self.deposite_money = deposite_money

    def run(self):
        self.acount.add_money(self.deposite_money)


@show_time
def main():
    threads = []
    my_count = Account()
    for thread in range(50):   # 用for循环创建50个线程
        a = Deposit_Money(my_count, 1)
        threads.append(a)
        a.start()
    for thread in threads:
        thread.join()   # 阻塞直到全部线程运行结束
    print(f'账户余款总数为:{my_count.show_money}')
    

if __name__ == '__main__':
    main()       
              
             

除了存钱的例子外,还有比如我使用一个线程对一个列表进行赋值,同一时间用另一个线程对同一个列表进行打印print()此时就会发现打印出来的可能就只是半个刚刚赋值的列表,这种情况也是冲突的。
对于函数的一些零散的应用,如map()和reduce()内置函数,map()函数有两个参数,第一个是函数,第二个一般是列表,返回的结果是对应值在函数中作用的结果。比如

def multi(x):
   return x**2
   
map(multi, [1, 3, 4, 5])
print(list(map(multi, [1, 3, 4, 5]))
# 结果会是 1, 9, 16, 25

map(int, input().split())
#一个个整数

而reduce中也是两个参数,一个函数,一个常为列表,但这个函数要两个参数,返回的结果为f(f(f(x1, x2), x3), x4)类型。
还有就是lambdas 的使用,comp = lambads x,y: x<y 若真就返回True,反之False.
在这吐槽一下那个不知怎么就热起来的秋天的第一杯奶茶,对我来说秋天的第一杯奶茶是是高攀不起了,但是再等等,我应该可以吃到冬天的第一口西北风。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值