线程

作者: 木叶苍蓝 | 来源:发表于2020-04-18 16:55 被阅读0次

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

1、使用threading模块
多线程执行
#coding=utf-8
import time

def sey_sorry():
    print("亲爱的,我错了,我能吃饭吗?")
    time.sleep(1)

if __name__ == "__main__":
    for i in range(5):
        t = threaeding.Thread(target=say_sorry)
        t.start()
多线程执行多个函数
#coding=utf-8
import time
import threading

def sing():
    for i in range(5):
        print("-------唱歌--------")
        time.sleep(1)

def dance():
    for i in range(5):
        print("--------跳舞---------")
        time.sleep(1)

def main():
    t1 = threading.Thread(target=sing)
    t2 = threading.Thread(target=dance)
    t1.start()
    t2.start()

if __name__ == "__main__":
    main()
查看线程数量
#coding=utf-8
import time
import threading

def sing()
    for i in range(5):
        print("正在唱歌...")
        time.sleep(1)

def dance():
    for i in range(5):
        print("正在跳舞...")
        time.sleep(1)

if __name__ == "__main__":
    print("------开始-----: %s"%(time.ctime(),))
    t1 = threading.Thread(target=sing)
    t2 = threading.Thread(target=dance)
    t1.start()
    t2.start()
    
    while True:
        length = len(threading.enumerate())
        print("当前运行线程数量: %s"%(length,))
        if length <= 1:
            break
        time.sleep(0.5)
线程执行代码的封装

通过使用threading模块能完成多任务的程序开发,为了让每个线程的封装性更完美,所以使用threading模块时,往往会定义一个新的子类class,只要继承threading.Thread就可以了,然后重写run方法。

#coding:=utf-8
import time
import threading

class MyThread(threading.Thread):
    def run(self):
        for i in range(3):
            time.sleep(1)
            msg = "I'm "+self.name+"@" +str(i)
            print(msg)
        self.login()
        self.register()
    def login(self):
        pass
    def register(self):
        pass
if __name__ == "__main__":
    t = MyThread()
    t.start()
多线程-共享全局变量
#coding=utf-8
import time
from threading import Thread

g_num = 100

def work1():
    global g_num
    for i in range(3):
        g_num += 1
    print("----in work1, g_num is %d-----"%(g_num,))

def work2():
    global g_num
    print("---in work2, g_num is %d-----"%(g_num,))

print("-----线程创建之前g_num is %d----"%(g_num,))
t1= Threaed(target=work1)
t1.start()
time.sleep(1)
t2 = Thread(target=work2)
t2.satrt()
多线程传参
#coding=utf-8
import ime
import threading

def test1(temp):
    temp.append(33)
    print("----in test1 temp = %s----"%(str(temp),))
def test2(temp):
    print("---in test2 temp = %s----"%(str(temp),))

g_nums = [11, 22]

def main():
    # target 指定要执行的线程
    # args 指定函数传递参数
    t1 = threaeding.Thread(target=test1, args=(g_nums,))
    t2 = threaeding.Thread(target=test2, args=(g_nums,))
    t1.start()
    time.slee(1)
    t2.start()
    time.sleep(1)
    print("----in main Thread g_nums = %s----"%(g_nums,))
if __nam__ == "__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调度为'runing'状态。t2也获得g_num=0。
  2. 然后t2对得到的g_num进行加1并赋值给g_num,使得g_num=1。
  3. 然后系统有把t2调度为'sleeping',把t1转为'runing',此时t1又把之前得到的g_num=0进行加1赋值给g_num。
  4. 虽然t1和t2都对g_num加1,但是g_num最后的结果还是1。
    这里就要加互斥锁来解决这个问题
# 创建锁
mutex = threading.Lock()
# 加锁
mutex.acquire()
# 解锁
mutex.release()

注意:

  • 如果这个锁之前是没有上锁的,那么acquire不会阻塞
  • 如果在调用acquire对这个锁上锁之前它已经被其他线程加锁了,那么此时acquire会阻塞,直到这个锁被解锁为止。
#coding=utf-8
# 使用互斥锁完成2个线程对同一个全局变量各加100万次
import time
import threading

g_num = 0

def test1(num):
    global g_num
    for i in range(num):
        mutex.acquire() # 上锁
        g_num += 1
       mutex.release() # 解锁
    print("----test1---g_num=%d"%(g_num,))

def test2(num):
    global g_num
    for i in range(num):
        mutex.acquire() # 上锁
        g_num += 1
        mutex.release() # 解锁
    print("----test2---g_num=%d"%(g_num,))

# 创建一个互斥锁
# 默认是未上锁状态
mutex = threading.Lock()
def main():
    t1 = threading.Thread(target=test1, args=(1000000, ))
    t2 = threading.Thread(target=test2, args=(1000000, ))
  
    t1.start()
    t2.start()

    # 等待上面2个线程执行完毕...
    time.sleep(2)
    print("---in main Thread g_num = %d----"%(g_num,))

if __nam__ == "__main__":
    main()
死锁

在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。
尽管死锁很少发生,一旦发生就会造成应用的停止响应。

#coding=utf-8
import time
import threaeding

class MyThreaed(threading.Thread):
    def run(self):
        # 对mutexA上锁
        mutexA.acquire()
        # mutexA上锁后,延迟1秒,等待另一个线程对mutexB上锁
        print(self.name + "----do 1 -- up ---")
         time.sleep(1)

        # 此时会阻塞,因为这个mutexB已经被另外一个线程抢先上锁了
        mutexB.acquire()
        print(self.name+"----do1---down----")
        mutexB.release()

        # mutexA解锁
        mutexA.release()

class MyThread2(threading.Thread):
    def run(self):
        # 对 mutexB上锁
        mutexB.acquire()

        # mutexB上锁后,延迟1秒,等待另外线程把mutexA上锁
        print(self.name+"------do2-----up----")
        time.sleep(1)

        # 此时会阻塞,因为这个mutexA已经被另外线程上锁了
        mutexA.acquirt()
        print(self,name+"----do2------down------")
        mutexA.release()

        # mutexB解锁
        mutexB.release()

mutexA = threading.Lock()
mutexB = threading.Lock()

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

    t1.start()
    t2.start()

相关文章

  • Android

    线程间通信 主线程和工作线程主线程和工作线程 工作线程与工作线程工作线程与工作线程 为什么主线程Looper.lo...

  • 三、操作系统之线程

    前言 什么是线程 引入线程的原因 线程的概念 线程和进程的关系 线程结构 线程有点 多线程模型 用户线程和内核线程...

  • Thread

    队列 线程锁 多线程,线程池 队列 多线程爬虫示例 多线程 自定义线程 线程池

  • 总结多线程与设计模式+synchronized+性能+高吞吐+死

    Java线程 Java语言的线程 何谓线程 线程启动 线程的暂时停止 线程的共享互斥 线程的协调 线程的状态转移 ...

  • 多线程编程

    摘要 线程概念,线程与进程的区别与联系学会线程控制,线程创建,线程终止,线程等待了解线程分离与线程安全学会线程同步...

  • java线程池

    线程VS线程池 普通线程使用 创建线程池 执行任务 执行完毕,释放线程对象 线程池 创建线程池 拿线程池线程去执行...

  • java并发之守护线程

    java中有两种线程,用户线程和守护线程用户线程:主线程停止时,用户线程不会停止守护线程:主线程停止时,守护线程也...

  • Java线程池的使用

    线程类型: 固定线程 cached线程 定时线程 固定线程池使用 cache线程池使用 定时调度线程池使用

  • 线程基础知识

    线程学习 线程的基础知识 线程是什么? 线程和进程的关系 线程的6个状态 线程优先级 主线程、多线程、后台线程的概...

  • 多线程介绍

    一、进程与线程 进程介绍 线程介绍 线程的串行 二、多线程 多线程介绍 多线程原理 多线程的优缺点 多线程优点: ...

网友评论

      本文标题:线程

      本文链接:https://www.haomeiwen.com/subject/zvqbvhtx.html