Python多线程

Python多线程

多任务不仅可以使用多进程完成,也可使用多线程完成。
一个进程可以包含很多线程,但至少含有一个线程。

Python提供了 _thread和threading两个模块,供我们使用多线程。_thread是低级模块,threading是高级模块。我们通常使用threading来实现多线程的相关功能。

使用线程读取文件内容。

  1. 读取文件内容的方法
  2. 创建线程,并将方法绑定到线程上
#!/usr/bin/env python3
# -*- coding:utf-8 -*-  
'多线程'
__author__ = 'click'
__date__ = '2018/7/23 下午6:20'

import time, threading


def threadReadFile():
    print('主线程的名字%s' % threading.current_thread().name)
    # print('读取文件中内容是%s' % myio.ReadAndWrite.readTxt())
    n = 0
    while n < 10:
        n = n + 1

    print('执行相加操作结果是%s' % n)


t = threading.Thread(target=threadReadFile, name='threadReadFile')
t.start()
t.join()
print("当前线城是%s" % threading.current_thread().name)

运行结果:

主线程的名字threadReadFile
执行相加操作结果是10
当前线城是MainThread

使用线程之前,先import threading要使用的threading模块。

t = threading.Thread(target=threadReadFile, name='threadReadFile')

初始化一个线程。

target:指定线程要执行的任务。

name:创建的线程的名称。

这样就实现了新创建一个线程,执行新任务。

提到多线程,就要考虑多线程之间操作同一变量时候,出现脏数据的问题。

来看看多线程是怎么样操作变量数据,导致多线程获取数据时候出错的。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-  
'多线程锁的问题'
__author__ = 'click'
__date__ = '2018/7/24 下午3:46'

import time, threading

'出现多线程数据混乱的问题:线程之间共享创建的全局变量' \
'多进程之间的变量:进程间相互独立的,不存在多进程操作同一变量' \
'多线程:共享同一变量,存在多线程对同一变量操作的情况'

#####################################
'多线程造成变量数据改变的原因' \
'原因是因为高级语言的一条语句在CPU执行时是若干条语句,即使一个简单的计算:'
'balance = balance + n'
'也分两步:'

'计算balance + n,存入临时变量中;'
'将临时变量的值赋给balance。'
'也就是可以看成:'

'x = balance + n'
'balance = x' \
    ####################################
'使用线程锁,对操作变量的方法进行加锁,保证变量值发生改变时只有一个线程对其操作。单线程的模式'

balance = 0

# 初始化一个锁
# 1. lock = threading.Lock()


def change_it(n):
    global balance
    balance = balance + n
    balance = balance - n


def run_thread(n):
    for i in range(1000000):
        # 1.首先申请锁
        # lock.acquire()
        try:
            change_it(n)
        finally:
            # 使用try  finaly 保证执行完之后,释放锁
           # lock.release()


t1 = threading.Thread(target=run_thread, args=(4,))
t2 = threading.Thread(target=run_thread, args=(6,))

t1.start()
t2.start()
t1.join()
t2.join()
print('balance %s' % balance)

先把锁相关的代码注释掉。

运行结果:

balance 4

按照代码正常的逻辑应该是如下:

n=4情况:
banlance =0
banlance = banlance+4  ->= banlance = 0+4 = 4
banlance = banlance-4  ->= banlance = 4-4 = 0

n=6情况:
banlance = 0
banlance = banlance +6 ->= banlance = 0+6 = 6
banlance = banlance -6 ->= banlance = 6-6 = 0

最后执行的结果banlance应该是0

那为什么会是4 呢?

创建多线程时候,应该按照先相加后相减。但是由于线程的调度是由操作系统直接控制。当t1,t2执行时,会出现交替执行的情况。这样最后banlance的值就不等于0。

这里面具体的原因是高级语言在执行一下代码时候,分为两部分执行,

banlance = banlance+n
1.计算banlance+n,并将值赋值给临时变量
2.将临时变量赋值给banlance

这样我们就清楚了,因为操作系统在执行代码时候分两步,当多线程执行时候,就会出现

t1
banlance = 0 
banlance = banlnace +4 ->= x = 0+4 = 4

t2
banlance = 0 
banlance = banlance +6 ->= Y = 0+6 = 6

最终
banlance = Y
 

当t1代码开始运行到banlance = X时候,banlance = 4。对于t2任务 banlance的数据已经是错的了。

综上,多线程导致数据出现错误的原因是,多个线程同时操作同一个变量,导致变量的值出现错误。

所以,我们要保证在t1在操作banlance的时候,其他的线程就不能操作banlance,其他的线程就要等待。只有当t1执行完毕,并释放了对banlance的锁,其他的线程才能进行操作banlance变量。

如何对一个变量进行加锁,

  • 初始化一个锁
    lock=threading.Lock()
  • 获取锁
    lock.acquire()
  • 将要执行的代码使用try...finaly处理,并在finaly中释放锁 lock.realease()

也就是放开上述代码中的1、2、3处代码。

运行代码结果为:

banlance = 0

多线程

加锁

你可能感兴趣的:(Python多线程)