• python-多任务编程01-线程(threading)


    并发:指的是任务数多余cpu核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不在执行,因为切换任务的速度相当快,看上去一起执行而已)

    并行:指的是任务数小于等于cpu核数,即任务真的是一起执行的

    线程

    python的thread模块是比较底层的模块,python的threading模块是对thread做了一些包装的,可以更加方便的被使用

    基本线程调用实例:

    import time
    import threading
    
    
    def dancing():
        for i in range(1, 4):
            print('跳舞中%d' % i)
            time.sleep(0.5)
        print('dancing 线程结束')
    
    
    def singing():
        for i in range(1, 5):
            print('唱歌中%d' % i)
            time.sleep(0.5)
        print('singing 线程结束')
    
    
    def main():
        # 创建子线程对象
        t1 = threading.Thread(target=dancing)
        t2 = threading.Thread(target=singing)
        # 子线程开始执行
        t1.start()
        t2.start()
        # 查看正在运行的子线程数量
        while True:
            length = len(threading.enumerate())
            print('当前运行的线程数为:%d' % length)
            if length <= 1:
                break
            time.sleep(0.2)
    
    
    if __name__ == '__main__':
        main()

    继承Thread类自定义类调用实例:

    import threading
    import time
    
    
    class DancingThread(threading.Thread):
        def run(self):
            for i in range(1, 3):
                print('线程名:%s,正在跳舞:。。。%d' % (self.name, i))
                time.sleep(0.5)
            print('
    跳舞线程结束')
    
    
    class SingingThread(threading.Thread):
        def run(self):
            for i in range(1, 5):
                print('线程名:%s,正在唱歌:。。。%d' % (self.name, i))
                time.sleep(0.5)
            print('唱歌线程结束')
    
    
    def main():
        # 创建Thread对象
        dancing = DancingThread()
        sing = SingingThread()
        # 调用run方法,开启线程
        dancing.start()
        sing.start()
    
    
    if __name__ == '__main__':
        main()

    线程共享全局变量

    • 在一个进程内的所有线程共享全局变量,很方便在多个线程间共享数据
    • 缺点就是,线程是对全局变量随意遂改可能造成多线程之间对全局变量的混乱(即线程非安全)
    • 假设两个线程t1和t2都要对全局变量g_num(默认是0)进行加1运算,t1和t2都各对g_num加10次,g_num的最终的结果应该为20。
    • 但是由于是多线程同时操作,有可能出现下面情况:
      1. 在g_num=0时,t1取得g_num=0。此时系统把t1调度为”sleeping”状态,把t2转换为”running”状态,t2也获得g_num=0
      2. 然后t2对得到的值进行加1并赋给g_num,使得g_num=1
      3. 然后系统又把t2调度为”sleeping”,把t1转为”running”。线程t1又把它之前得到的0加1后赋值给g_num。
      4. 这样导致虽然t1和t2都对g_num加1,但结果仍然是g_num=1
    import threading
    import time
    
    g_num = 0
    
    
    class DancingThread(threading.Thread):
        def __init__(self, num):
            threading.Thread.__init__(self)
            self.num = num
    
        def run(self):
            global g_num
            for i in range(self.num):
                g_num += 1
            print('跳舞线程结束,g_num:%d' % g_num)
    
    
    class SingingThread(threading.Thread):
        def __init__(self, num):
            threading.Thread.__init__(self)
            self.num = num
    
        def run(self):
            global g_num
            for i in range(self.num):
                g_num += 1
            print('唱歌线程结束,g_num:%d' % g_num)
    
    
    def main():
        # 创建Thread对象
        dancing = DancingThread(1000000)
        sing = SingingThread(1000000)
        # 调用run方法,开启线程
        print('初始g_num: %d' % g_num)
        dancing.start()
        sing.start()
        # 等待子线程运行完
        while len(threading.enumerate()) > 1:
            time.sleep(1)
        print('线程结束后g_num: %d' % g_num)
    
    
    if __name__ == '__main__':
        main()

    运行结果为:

    初始g_num: 0
    跳舞线程结束,g_num:1292807
    唱歌线程结束,g_num:1712212
    线程结束后g_num: 1712212

    使用互斥锁解决线程冲突

    # 创建锁
    mutex = threading.Lock()
    # 锁定
    mutex.acquire()
    # 释放
    mutex.release()
    import time
    import threading
    g_num = 0
    
    
    def dancing(num, mutex):
        global g_num
        for i in range(num):
            # 上锁
            mutex.acquire()
            # 计算
            g_num += num
            # 解锁
            mutex.release()
    
        print('dancing 线程结束,num值: %d' % g_num)
    
    
    def singing(num, mutex):
        global g_num
        for i in range(num):
            # 上锁
            mutex.acquire()
            # 计算
            g_num += num
            # 解锁
            mutex.release()
    
        print('dancing 线程结束,num值: %d' % g_num)
    
    
    def main():
        print('初始值:%d' % g_num)
        # 创建锁对象
        mutex = threading.Lock()
        # 创建子线程对象
        t1 = threading.Thread(target=dancing, args=(1000000, mutex, ))
        t2 = threading.Thread(target=singing, args=(1000000, mutex, ))
        # 子线程开始执行
        t1.start()
        t2.start()
    
    
    if __name__ == '__main__':
        main()

    运行结果:

    初始值:0
    dancing 线程结束,num值: 1876392000000
    dancing 线程结束,num值: 2000000000000
  • 相关阅读:
    九个合理的个人所得税避税方案
    百度搜索技巧
    jsoup方法string转document
    java正则
    多线程之join方法
    java获取当前日期时间代码总结
    Error与Exception的区别,Java常见异常Execption总结
    Google Chrome调试js入门
    Resource temporarily unavailable用户的连接数设置的太小
    所有javax包
  • 原文地址:https://www.cnblogs.com/gcxblogs/p/12930887.html
Copyright © 2020-2023  润新知