线程

1.创建线程的第一种方法(后面讲解第二种方法)

导入:import threading

创建一个线程的执行计划:thd=threading.Thread(target=方法名)

启动线程:thd.start()

例子:

import threading
import time

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

if __name__ == '__main__':
    for i in range(5):
        # 创建一个线程的执行的计划
        thd=threading.Thread(target=saySorry)

        # 启动线程
        thd.start()

开启线程,相当于一个进程中开启了五个分支,5个分支同时进行

2.查看当前进程内部存活的所有线程列表

threading.enumerate()

3.等待子线程执行结束之后主线程才继续执行(等待子线程完成之后,继续)

import threading

def dance():
    for i in range(5):
        print("正在跳舞... %d" %i)

if __name__ == '__main__':
    thd=threading.Thread(target=dance)
    thd.start()
    print("太棒了")

执行结果:

 

但是有时候想子线程执行完之后才让主线程继续执行

就使用thd.join(),这个方法类似于主线程执行到这个位置,等待子线程结束才继续执行

import threading

def dance():
    for i in range(3):
        print("正在跳舞... %d" %i)

if __name__ == '__main__':
    thd=threading.Thread(target=dance)
    thd.start()

    # 主线程阻塞等待 Thread对象标识的子线程退出之后 才会继续执行
    thd.join()
    print("太棒了")

4.创建线程的第二种方法

1.创建一个类,并继承Thread

2.实现其中的run方法(run方法在Thread类中已经实现了,就相当于重写该方法,在这个run方法中就是子线程里运行的方法,相当于上面写的dance方法)

3.创建该类的实例对象

4.实例对象.start()启动创建和执行

import threading

class myThread(threading.Thread):
    """1. 继承Thread 2. 实现其中run方法 3. 创建该类的实例对象 4. 对象.start()启动创建和执行"""
    def run(self):
        for i in range(3):
            print("在子线程中")

if __name__ == '__main__':
    mt=myThread()
    mt.start()
    print("主线程")

5.多线程共享全局变量引起资源竞争混乱及解决方法

比如:火车票的数量,如果同时有3个人购买火车票,而火车票的数量是100张,当第一个人购买后火车票的数量就会变成99,此时数据库就会将100这个值修改成99,而第二个人也是在这一时刻购买火车票,此时第二个人的火车票数量也是100,提交的时候就变成了99,第三个人也同样是这样(就是说这三个人在同时刻同时修改数据库里的火车票数量),假设可以提交,那么实际上火车在数据库里的数量就是99,但是已经卖出去了3张,那么就会出现数据不准的情况。这就是全局变量引起的资源竞争混乱。

import threading

# 全局变量
g_number=0

def add1():
    global g_number
    for i in range(1000000):
        g_number+=1

def add2():
    global g_number
    for i in range(1000000):
        g_number+=1


if __name__ == '__main__':
    th1=threading.Thread(target=add1)
    th1.start()
    th2=threading.Thread(target=add2)
    th2.start()

    th1.join()
    th2.join()
    print("结果:%d" %g_number)

这段代码,如果按照设想结果的话:g_number的结果是2000000

实际结果如下:

原因就是在某一刻时间内add1,add2获取g_number的时候值相同,但是提交结果都加1,然后一个值覆盖另一个值,那么就会出现这种情况

解决的方法:创建一个全局互斥锁,在一个线程修改这个全局变量的时候,不让别的线程修改,阻塞等待,如果修改完了,才让另一个线程修改这个全局变量值

import threading

# 全局变量
g_number=0
# 创建一把全局互斥锁
g_lock=threading.Lock()

def add1():
    global g_number
    for i in range(1000000):
        g_lock.acquire() # 尝试获取并且加锁,如果没有被锁定,就可以被我锁定;如果被锁定了,阻塞等待直到成功获取并锁定
        g_number+=1
        g_lock.release() # 操作完g_number变量释放锁资源,也就是解锁

def add2():
    global g_number
    for i in range(1000000):
        g_lock.acquire()
        g_number+=1
        g_lock.release()


if __name__ == '__main__':
    th1=threading.Thread(target=add1)
    th1.start()
    th2=threading.Thread(target=add2)
    th2.start()

    th1.join()
    th2.join()
    print("结果:%d" %g_number)

第二种实现的方法:

import threading

# 全局变量
g_number=0
# 创建一把全局互斥锁
g_lock=threading.Lock()

def add1(lock):
    global g_number
    for i in range(1000000):
        lock.acquire() # 尝试获取并且加锁,如果没有被锁定,就可以被我锁定;如果被锁定了,阻塞等待直到成功获取并锁定
        g_number+=1
        lock.release() # 操作完g_number变量释放锁资源,也就是解锁

def add2(lock):
    global g_number
    for i in range(1000000):
        lock.acquire()
        g_number+=1
        lock.release()


if __name__ == '__main__':
    th1=threading.Thread(target=add1,args=(g_lock,))
    th1.start()
    th2=threading.Thread(target=add2,args=(g_lock,))
    th2.start()

    th1.join()
    th2.join()
    print("结果:%d" %g_number)

原文地址:https://www.cnblogs.com/fjiqiang/p/10578178.html