Python中的多线程编程

本文介绍了线程的基础概念,包括创建子线程的方法、主线程与子线程间的执行顺序控制,以及解决线程安全问题的技术手段。通过具体示例展示了如何在Python中实现多线程编程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:
线程是操作系统能够进行运算调度的最小单位(程序执行流的最小单元)
它被包含在进程之中,是进程中的实际运作单位
一个进程中可以并发多个线程每条线程并行执行不同的任务
(线程是进程中的一个实体,是被系统独立调度和分派的基本单元)
每一个进程启动时都会最先产生一个线程,即主线程
然后主线程会再创建其他的子线程

一、创建子线程

1.创建一个子线程

from threading import Thread

def Foo(arg):
    print arg

print 'before'
# 线程和函数建立关系
t1 = Thread(target=Foo, args=(1,))
t1.start()
print 'after'

这里写图片描述

2.创建多个子线程

# 导入创建子线程的工具
from threading import Thread
def Foo(arg):
    print arg

print 'before'
# 利用Thread创建一个子线程t1
# target是调用的函数,args是调用函数的参数,单个参数后要加逗号
t1 = Thread(target=Foo,args=(1,))
# 启动子线程
t1.start()
#输出子线程的名称
print t1.getName()

t2 = Thread(target=Foo,args=(2,))
t2.start()
print t2.getName()

print 'after'

这里写图片描述

3.模拟问题

import threading
import Queue
import time
import random
def Producer(name,que):
    while True:
        if que.qsize() <3:
            que.put('baozi')
            print '%s:Made a baozi..=============' % name
        else:
            print '还有三个包子'
        time.sleep (random.randrange(5))

def Consumer(name,que):
    while True:
        try:
            que.get_nowait()
            print '%s:Got a baozi..' % name
        except Exception:
            print '没有包子了'
        time.sleep(random.randrange(3))
# 创建队列
q = Queue.Queue()

p1 = threading.Thread(target=Producer,args=['chef1',q])
p2 = threading.Thread(target=Producer,args=['chef2',q])
p1.start()
p2.start()

c1 = threading.Thread(target=Consumer,args=['tom',q])
c2 = threading.Thread(target=Consumer,args=['harry',q])
c1.start()
c2.start()

二、主线程和子线程的执行等待问题

一个多线程程序,当主线程创建之后又有其他的子线程,就存在执行完成的先后顺序

1.主线程执行完毕不等待子线程

from threading import Thread
import time
def Foo(arg):
    for item in range(10):
        print item
        time.sleep(1)
print 'before'
t1 = Thread(target=Foo,args=(1,))
# 主线程执行完就结束程序,不在乎子线程的结束与否
# 主进程执行完了就不再等待子线程,False表示等待子线程
t1.setDaemon(True)
t1.start()
print 'after'

这里写图片描述

2.决定主线程等待子线程的时间

join()括号中可以写主线程等待子线程的时间
不写表示等待子线程执行完主线程再开始执行

from time import sleep
from threading import Thread
def Foo():
    for item in range(10):
        print item
        sleep(1)

print 'before'
# 线程和函数建立关系
t1 = Thread(target=Foo)
t1.start()
# 主线程到join()就不往下进行了,直到子线程执行完
t1.join(5)
print 'after'

这里写图片描述

三、子线程完成多件任务

创建子线程来模拟同时看电影和听音乐

from threading import Thread
from time import ctime,sleep
def music(a):
    for i in range(1):
        print 'I was listening to %s. %s\n' % (a,ctime())
        sleep(1)


def movie(b):
    for i in range(1):
        print 'I was watching to %s. %s\n' % (b,ctime())
        sleep(5)

# music('hello')
# movie('titanic')
t1 = Thread(target=music,args=('hello',))
t1.start()

t2 = Thread(target=movie,args=('titanic',))
t2.start()
t2.join()
print 'All over %s' % ctime()

运行结果如下,可以看到看电影和听音乐同时进行
这里写图片描述

四、线程安全问题

1.基本概念

线程不安全:就是不提供数据访问保护,在多线程环境中对数据进行修改,会出现数据不一致的情况。
线程安全:就是多线程环境中有对全局变量的变动时,需要对执行的代码块采用锁机制,当一个线程访问到某个数据时,其他线程需要等待当前线程执行完该代码块才可执行,不会出现数据不一致或者数据被污染。

如果一段代码在被多个线程执行,如果每次运行结果和单线程运行的结果是一样的,而且其他变量的值和预期一样,就是线程安全的。

线程安全主要由对有全局变量或静态变量有修改动作而引起的。

2.实例演示

import threading
import time
num = 0
def run(n):
    time.sleep(1)
    global num
    num += 1
    print '%s\n' % num

for i in range(1500):
    t=threading.Thread(target=run,args =(i,))
    t.start()

这里写图片描述
进行改进:

import threading
import time
num = 0
def run(n):
    time.sleep(1)
    global num
    # 对数据加锁
    lock.acquire()
    num += 1
    print '%s\n' % num
    # 释放加的锁
    lock.release()
# 生成一个锁
lock = threading.Lock()
for i in range(1500):
    t=threading.Thread(target=run,args =(i,))
    t.start()

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值