多个线程之间,是共享全局变量的
验证:
代码:
import threading
import time
# 定义一个全局变量
g_num = 100
def test1():
global g_num
g_num += 1
print("----in test1 g_num=%d----" % g_num)
def test2():
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()
输出结果:
输出的值都是一样的
全局变量之所以能共享,是因为开发者在开发Python时考虑到,执行多任务时,往往是需要相互之间配合使用的。
多线程开发可能遇到的问题
假设两个线程test1和test2都要对全局变量g_num(默认=0)进项加1运算,两个线程都对g_num加10次,g_num最终结果应该为20
但由于是多线程同时操作,有可能出现下面情况:
- 在g_num=0时,t1取得的值是0,此时系统把t1调度为sleeping状态,把t2转化个为running状态,则t2取得值也是0
- 然后t2对得到的值进行加1并赋给t1,使得g_num= 1
- 然后系统又把t2调度为sleeping状态,t1转换为running状态,线程t1又把它之前得到的0加1后赋值给g_num
- 这样导致虽然t1和t2都对g_num加1,明明执行了两次加1,但是最后结果任然是g_num=1
验证:
代码:
import threading
import time
# 定义一个全局变量
g_num = 0
def test1(num):
global g_num
for i in range(num):
g_num += 1
print("----in test1 g_num=%d----" % g_num)
def test2(num):
global g_num
for i in range(num):
g_num += 1
print("----in test2 g_num=%d----" % g_num)
def main():
t1 = threading.Thread(target=test1, args=(1000000,))
t2 = threading.Thread(target=test2, args=(1000000,))
t1.start()
t2.start()
# 等待上面的两个线程执行完毕
time.sleep(5)
print("----in main Thread g_num = %d" % g_num)
if __name__ == "__main__":
main()
输出结果:
相加的次数越多,后面的差值就越大
这个问题是可以解决的:
可以通过线程同步来进行解决:
- 系统调用t1,然后获取到g_num的值为0,此时上一把锁,既不允许其他的线程操作g_num
- t1对g_num的值进行加1
- t1解锁,此时g_num的值为1,其他的线程就可以使用g_num了,而且是g_num的值不是0而是1
- 同理其他线程在对g_num进行修改是,都要先上锁,处理完成后再解锁
同步的概念:
同步就是协同步调,按预定的先后次序进行运行
互斥锁:
当多个线程几乎同时修改某一个共享数据时,需要进行同步控制
某个线程要更改共享数据时,现将其锁定,此时资源的状态为锁定,其他的线程不能操作更改,直到该线程释放资源,将资源的状态变成非锁定,其他的线程才能再次锁定该资源,互斥锁保证了每次只有一个线程进行操作,从而保证了多线程情况下数据的正确性
创建锁
mutex = threading.Lock()
锁定
mutex.acquire()
释放
murex.release()
·如果这个锁之前是没有上锁的,那么acquire不会堵塞
·如果在调用acquire对这个锁上锁之前,它已经被其他线程上锁,那么此时acquire会堵塞,直到这个锁被解锁为止
操作:
代码:
import threading
import time
# 定义一个全局变量
g_num = 0
def test1(num):
global g_num
# 上锁,如果之前没有被上锁,此时上锁成功
# 如果上锁之前,已经被上锁,会堵塞,直到被解锁
mutex.acquire()
for i in range(num):
g_num += 1
# 解锁
mutex.release()
print("----in test1 g_num=%d----" % g_num)
def test2(num):
global g_num
mutex.acquire()
for i in range(num):
g_num += 1
mutex.release()
print("----in test2 g_num=%d----" % g_num)
# 创建一个互斥锁,默认没有上锁的
mutex = threading.Lock()
def main():
t1 = threading.Thread(target=test1, args=(10000000,))
t2 = threading.Thread(target=test2, args=(10000000,))
t1.start()
t2.start()
# 等待上面的两个线程执行完毕
time.sleep(5)
print("----in main Thread g_num = %d" % g_num)
if __name__ == "__main__":
main()
输出结果:
版权声明:本文为arizia原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。