1. 线程之间是共享全局变量的
验证代码:
import threading
import time
# 定义一个全局变量
g_num = 100
def test1(): # 修改g_num的值
global g_num
g_num += 1
print("-----in test1 g_num=%d-----"%g_num)
def test2(): # 打印g_num
print("-----in test2 g_num=%d-----"%g_num)
def main():
t1 = threading.Thread(target=test1)
t2 = threading.Thread(target=test2)
t1.start()
time.sleep(1)
t2.start()
time.sleep(1)
print("-----in main Thread g_num = %d-----"% g_num)
if __name__ == '__main__':
main()
结果为: 可以看到在test1函数中利用子线程修改了值,在test2中和主函数中也会改变
-----in test1 g_num=101-----
-----in test2 g_num=101-----
-----in main Thread g_num = 101-----
2.共享全局变量的问题:----->会产生资源竞争的问题
利用线程同步的互斥锁来解决
(1) 同步: 同步就是协同步调,按预定的先后次序进行运行。
“同”: 不是一起动作,而是指协同、协助、互相配合。
如进程、线程同步,可理解为进程或线程A和B一块配合执行,A执行到一定程度时要依靠B的某个结果,于是停下 来,示意B运行,再将结果给A,A再执行
(2)互斥锁: 当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制
互斥锁为资源引入一个状态: 锁定/非锁定可以这样理解:
某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改,直到该线程释放 资 源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。
(3) 创建互斥锁(threading模块中定义Lock类,可以方便的处理锁定):
mutex = threading.Lock() # 创建
mutex.acquire() # 锁定 (上锁)
mutex.release() # 释放 (解锁)
同一把锁只能上一次,创建后默认是没有上锁的状态,那么acquire()不会堵塞,如果已经被其他线程上了锁,那么 此 时acquire()就会堵塞,直到这个锁被解锁为止。
如下例子:
(1) 没加锁之前,进行一个加法运算,会发现结果不对,,没加锁之前运行的结果是
-----in test1 number=1084914----- -----in test2 number=1156328----- -----in main number=1156328-----(2)加上锁之后,随便运行结果都是正确的:
-----in test1 number=1000000----- -----in test2 number=2000000----- -----in main number=2000000-----
加上锁之后的代码
import threading
import time
# 定义一个全局变量
number = 0
'''创建一个互斥锁,默认是没有上锁的'''
mutex = threading.Lock()
def test1(temp):
global number
'''上锁'''
mutex.acquire()
for i in range(temp):
number += 1
'''解锁'''
mutex.release()
print("-----in test1 number=%s-----" % number)
def test2(temp):
global number
'''上锁'''
mutex.acquire()
for i in range(temp):
number += 1
'''解锁'''
mutex.release()
print("-----in test2 number=%s-----" % number)
def main():
t1 = threading.Thread(target=test1,args=(1000000,)) # 加上要传递的参数,元组类型
t2 = threading.Thread(target=test2, args=(1000000,))
t1.start()
t2.start()
time.sleep(2)
print("-----in main number=%s-----"% number)
if __name__ == '__main__':
main()