py - 多线程 -threading模块

为了解决在一个程序中多个函数或多处地方一起执行一起执行的问题
线程:就是实现多任务的一种手段 在一个程序运行起来以后一定有一个执行代码东西 这个东西就叫做线程

主要思路:
先创建一个theading.Thread()的实例对象 并给出实例对象的参数 也就是创造一个子线程
用实例对象调用start()方法
threading.Thread(target=def,args=parameter)
def 表示将来,这个线程去哪个函数执行代码
parameter 表示指定将来调用 函数的时候 传递什么参数过去 一定时个元组 不是元组程序壁

例 代码

import time
import threading

#创建测试函数 sing
def sing():
    for i in range(5):
        print("--------正在唱歌------")
        time.sleep(1)

#创建测试函数dunce
def dunce():
    for i in range(5):
        print("-------正在跳舞--------")
        time.sleep(1)


def main():
	#创建第一个Thread对象 t1 并将测试函数sing 的函数名一参数给如Thread方法
    t1 = threading.Thread(target=sing)
    #创建第二个Thread对象 t2 并将测试函数dunce 的函数名一参数给如Thread方法
    t2 = threading.Thread(target=dunce)
    #t1 t2 调用start放方法开始执行子进程
    t1.start()
    t2.start()


if __name__ == "__main__":
    main()

输出结果:

	--------正在唱歌------
	-------正在跳舞--------
	--------正在唱歌------
	-------正在跳舞--------
	--------正在唱歌------
	-------正在跳舞--------
	--------正在唱歌------
	-------正在跳舞--------
	-------正在跳舞--------
	--------正在唱歌------

当主进程没有代码执行时,会等待子进程执行结束
子线程实在threading.Thread创建的实例对象调用此对象的start()时创建和开始工作的
子线程的死亡时间时是子线程执行的程序结束的时间
当主进程结束时,整个程序也就结束了
若在执行中主线程先死亡,子线程也会跟着死

查看程序中一共有多少线程 threading.enumerate
进程执行没有先后 想控制线程的执行先后可以控制线程的延迟达到控制线程的先后

Tread调用类

1这个类必须继承于threading.Thread
2必须要存在run函数

import time
import threading

class Modle(threading.Thread):
    def run(self):
        for i in range(3):
            time.sleep(1)
            print("1---")


if __name__ == "__main__":
    t = Modle()
    t.start()

执行结果:
1—
1—
1—

在调用类时 调用start方法时会自动调用类当中run方法
调用类适合于一个线程中做的事情比较复杂 在一个类中分成多个函数使用
在创建的对象中调用start方法时只会执行一个run方法 让其余的方法被run方法调用
子线程之间共享全局变量

互斥锁 threading.Lock

当多个线程几乎同时四u该某一个共享数据的时候,需要进行同步控制
线程同步能够保证多个线程安全访问竞争资源,最简单的机制时引入互斥锁
互斥锁为资源引入一个状态:锁定/非锁定
	某个线程要更改共享数据时,先将其锁定,此时i资源进入锁定状态,其他相乘不能惊醒更改:知道该线程释放资源,将资源改成非锁定,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程下数据的正确性

#创建互斥锁
mutex = threading.Lock()
#锁定
mutex.acqurie()
#释放(互斥锁解锁)
mutex.release()

例:解决 ------共享全局变量资源竞争
#没上互斥锁的情况
import time
import threading

g_num = 0


def test1(num):
    global g_num
    for i in range(num):
        g_num += 1
    print("----------1-----------")


def test2(num):
    global g_num
    for i in range(num):
        g_num += 1
    print("----------2-----------")


def main():
    t1 = threading.Thread(target=test1, args=(1000000,))
    t2 = threading.Thread(target=test2, args=(1000000,))

    t1.start()
    t2.start()

    time.sleep(5)
    print("%d" % g_num)


if __name__ == "__main__":
    main()

代码执行结果:

----------1-----------
----------2-----------
1146329

由于在运行过程中test1的执行结果纷纷为三个步骤
1.取到全局变量g_num变量
2.让全局变量g_num加1
3.把全局变量放回内存
由于在执行中cpu时让每一个线程执行一会
所以在全局变量未放回内存中时执行了另一个线程所以会有全局变量的资源竞争
产生了+1冲突 重复累加 而产生计算结果错误
用互斥锁就可以解决此问题

解决方法1

#采用互斥锁

import time
import threading

g_num = 0
# 创建一个互斥锁
mutex = threading.Lock()


def test1(num):
    global g_num
    # 上锁,如果没有上锁,此时上锁成功
    # 如果上锁之前,已经被上锁,则会堵塞在这里,直到这个锁被解开
    mutex.acquire()
    for i in range(num):
        g_num += 1
    # 解锁
    mutex.release()
    print("----------1-----------")


def test2(num):
    global g_num
    mutex.acquire()
    for i in range(num):
        g_num += 1
    mutex.release()
    print("----------2-----------")


def main():
    t1 = threading.Thread(target=test1, args=(1000000,))
    t2 = threading.Thread(target=test2, args=(1000000,))

    t1.start()
    t2.start()

    time.sleep(5)
    print("%d" % g_num)


if __name__ == "__main__":
    main()

输出结果:
----------1-----------
----------2-----------
2000000

解决方法2
import time
import threading

g_num = 0
# 创建一个互斥锁
mutex = threading.Lock()


def test1(num):
    global g_num

    for i in range(num):
    # 上锁,如果没有上锁,此时上锁成功
    # 如果上锁之前,已经被上锁,则会堵塞在这里,直到这个锁被解开
        mutex.acquire()
        g_num += 1
        # 解锁
        mutex.release()

    print("----------1-----------")


def test2(num):
    global g_num
    for i in range(num):
        mutex.acquire()
        g_num += 1
        mutex.release()
    print("----------2-----------")


def main():
    t1 = threading.Thread(target=test1, args=(1000000,))
    t2 = threading.Thread(target=test2, args=(1000000,))

    t1.start()
    t2.start()

    time.sleep(5)
    print("%d" % g_num)


if __name__ == "__main__":
    main()

执行结果:
----------2-----------
----------1-----------
2000000

互斥锁锁定的代码尽量短
否则可能产生由于某一个代码片段延迟过高而降低整体的运行速度
在一个代码快中 若存在太多的互斥锁 则有可能出现死锁的情况
在设计程序时要尽量避免死锁
添加超时时间等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值