通过轮询的方式解决线程间共享全局变量的问题

from threading import Threadg_num = 0
g_flag = 1  # 增加一个标识全局变量def test1():global g_numglobal g_flagif g_flag == 1:for i in range(1000000):g_num += 1g_flag = 0print('---test1 g_num is %d---' % g_num)def test2():global g_num# 轮询while True:if g_flag != 1: # 一旦test1()执行完,即g_flag = 0时,test2()开始执行累加g_num操作for i in range(1000000):g_num += 1breakprint('---test2 g_num is %d---' % g_num)t1 = Thread(target=test1)
t1.start()t2 = Thread(target=test2)
t2.start()print('-----g_num: %d-----' % g_num)

线程间使用非全局变量

from threading import Thread
import threading
import timedef test1():name = threading.current_thread().name  # 获取当前线程名字print('----thread name is %s----' % name)g_num = 100if name == 'Thread-1':g_num += 1else:time.sleep(2)print('---thread is %s | g_num is %d---' % (name, g_num))t1 = Thread(target=test1)
t1.start()t2 = Thread(target=test1)
t2.start()

通过互斥锁解决线程间共享全局变量的问题

from threading import Thread, Lock  # 导入互斥锁g_num = 0def test1():global g_numfor i in range(1000000):mutex.acquire()  # 上锁,此时其他的锁会等待  上锁应该遵循最小原则g_num += 1mutex.release() # 开锁,此时其他的锁会抢着开锁print('---test1 g_num is %d---' % g_num)def test2():global g_numfor i in range(1000000):mutex.acquire()g_num += 1mutex.release()print('---test2 g_num is %d---' % g_num)# 创建一把互斥锁,默认不上锁
mutex = Lock()t1 = Thread(target=test1)
t1.start()t2 = Thread(target=test2)
t2.start()print('-----g_num: %d-----' % g_num)

通过互斥锁解决线程间共享全局变量的问题-修改后的代码

from threading import Thread, Lock  # 导入互斥锁g_num = 0def test1():global g_nummutex.acquire()  # 上锁,此时其他的锁会等待  上锁应该遵循最小原则for i in range(1000000):g_num += 1mutex.release() # 开锁,此时其他的锁会抢着开锁print('---test1 g_num is %d---' % g_num)def test2():global g_nummutex.acquire()for i in range(1000000):g_num += 1mutex.release()print('---test2 g_num is %d---' % g_num)# 创建一把互斥锁,默认不上锁
mutex = Lock()t1 = Thread(target=test1)
t1.start()t2 = Thread(target=test2)
t2.start()print('-----g_num: %d-----' % g_num)# 值得注意的是,互斥锁上的范围太大就失去了线程的意义,别的线程都把时间浪费在了等待上.轮询同理.

线程死锁

import threading
import timeclass MyThread1(threading.Thread):def run(self):if mutexA.acquire():print(self.name + '---do1---up---')time.sleep(1)if mutexB.acquire():print(self.name + '---do1---down---')mutexB.release()mutexA.release()class MyThread2(threading.Thread):def run(self):if mutexB.acquire():print(self.name + '---do2---up---')time.sleep(1)if mutexA.acquire():print(self.name + '---do2---down---')mutexA.release()mutexB.release()if __name__ == '__main__':mutexA = threading.Lock()mutexB = threading.Lock()t1 = MyThread1()t2 = MyThread2()t1.start()t2.start()

分析代码,t1的代码在等待mutexB解锁的时候t2在等待mutexA解锁.
而t1必须先执行完mutexB锁中的代码执行完才能释放mutexA,
t2必须先执行完mutexA锁中的代码执行完才能释放mutexB,
这就导致两个线程一直等待下去形成死锁,会浪费CPU资源.

解决死锁办法:
设置超时时间 mutexA.acquire(2)
当然也可以从算法上避免死锁

使用ThreadLocal

import threading# 创建全局ThreadLocal对象
local_school = threading.local()def process_student():# 获取当前线程相关联的studentstd = local_school.studentprint('Hello, %s in %s' % (std, threading.current_thread().name))def process_thread(name):# 绑定ThreadLocal的studentlocal_school.student = nameprocess_student()t1 = threading.Thread(target=process_thread, args=('kain',), name='Thread-A')
t2 = threading.Thread(target=process_thread, args=('huck',), name='Thread-B')t1.start()
t2.start()
t1.join()
t2.join()

ThreadLocal是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只有在指定的线程中可以获取到存储的数据,对于其他线程来说则无法取到数据。

生产者和消费者问题

import threading
import time# Python2
# from Queue import Queue# Python3
from queue import Queueclass Producer(threading.Thread):def run(self):global queuecount = 0while True:if queue.qsize() < 1000:for i in range(100):count += 1msg = '生成产品' + str(count)queue.put(msg)print(msg)time.sleep(0.5)class Consumer(threading.Thread):def run(self):global queuewhile True:if queue.qsize() > 100:for i in range(3):msg = self.name + '消费了' + queue.get()print(msg)time.sleep(1)if __name__ == '__main__':queue = Queue()for i in range(500):queue.put('初始产品'+str(i))    # 向队列中塞内容for i in range(2):p = Producer()p.start()for i in range(5):c = Consumer()c.start()

线程死锁与共享变量的使用(转载)相关推荐

  1. 网络瓶颈、线程死锁、内存泄露溢出、栈堆、ajax

    网络瓶颈:网络传输性能及稳定性的一些相关元素 线程死锁:多个线程因竞争资源造成的一种僵局 下面我们通过一些实例来说明死锁现象. 先看生活中的一个实例,2个人一起吃饭但是只有一双筷子,2人轮流吃(同时拥 ...

  2. JAVA笔记14__多线程共享数据(同步)/ 线程死锁 / 生产者与消费者应用案例 / 线程池...

    /*** 多线程共享数据* 线程同步:多个线程在同一个时间段只能有一个线程执行其指定代码,其他线程要等待此线程完成之后才可以继续执行.* 多线程共享数据的安全问题,使用同步解决.* 线程同步两种方法: ...

  3. 什么是线程死锁?如何解决?(蚂蚁金服面试题)

    认识线程死锁 多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放.由于线程被无限期地阻塞,因此程序不可能正常终止. 如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想 ...

  4. linux查看java线程死锁_ccriticalsection 多线程 死锁_c++ 线程死锁_linux 线程 死锁

    qq_407283393122018-12-10 一个很蠢的造成死锁的问题 wanglt3113172018-12-12 什么是死锁,死锁的原因,如何避免 apanying902019-01-09 c ...

  5. Android 线程死锁的案例

    模拟java 线程死锁 ExecutorService executorService = Executors.newFixedThreadPool(2);Object lockA =new Obje ...

  6. troubleshoot之:用control+break解决线程死锁问题

    简介:如果我们在程序中遇到线程死锁的时候,该怎么去解决呢? 本文将会从一个实际的例子出发,一步一步的揭开java问题解决的面纱. 简介 如果我们在程序中遇到线程死锁的时候,该怎么去解决呢? 本文将会从 ...

  7. java中线程死锁及避免_如何避免Java线程中的死锁?

    java中线程死锁及避免 如何避免Java中的死锁? 是Java面试中最受欢迎的问题之一,也是本季多线程的风格,主要是在高层提出,并带有很多后续问题. 尽管问题看起来很基础,但是一旦您开始深入研究,大 ...

  8. java线程死锁_Java并发:隐藏线程死锁

    java线程死锁 大多数Java程序员熟悉Java线程死锁概念. 它本质上涉及2个线程,它们彼此永远等待. 这种情况通常是平面(同步)或ReentrantLock(读或写)锁排序问题的结果. Foun ...

  9. java线程死锁_Java线程死锁–案例研究

    java线程死锁 本文将描述从在IBM JVM 1.6上运行的Weblogic 11g生产系统中观察到的最新Java死锁问题的完整根本原因分析. 此案例研究还将证明掌握线程转储分析技能的重要性: 包括 ...

最新文章

  1. video标签支持获取rtsp流么_Flask教程(二十二)在浏览器中播放rtsp实时流
  2. 集群调度框架的架构演进之路
  3. Linux之文件查找
  4. 算法转AI平台工程师记录-0
  5. rs485如何使用_12个经典问答:带你全面了解RS485接口知识
  6. java面向对象的特征二:继承性 —(14)
  7. 北大教授最短毕业致辞。#人性的可爱 #饶毅#自我尊重
  8. hadoop记录topk
  9. 2021科技创新者大会:“武汉永远是一座造光之城”
  10. 【java学习之路】(java SE篇)(练习)集合练习:经典例题
  11. Halcon深度学习总结
  12. ChIP-Atlas:基于公共chip_seq数据进行分析挖掘
  13. android 比较全的android 源码合集 + 企业级应用分享,从业的积累(毕业设计集合版)
  14. android webview 之 AgentWeb的使用
  15. python 修改文件只读_Python脚本去除文件的只读性操作
  16. 【19】processing-硬件(中文)
  17. 网络服务器带宽Mbps、Mb/s、MB/s有什么区别?10M、100M到底是什么概念?
  18. 神码ai人工智能写作机器人_人工智能和机器学习可以改善营销的6种方式
  19. 数据把脉,智慧防灾——推进自然灾害应急管理信息化建设的思考
  20. 冒泡社区一直连接服务器,冒泡社区.幻想三国的服务器是什么?

热门文章

  1. Codeforces Round #408 (Div. 2)
  2. c 整数的逆序输出 输入3,2就算 2+22+222的结果
  3. Java_01_Java读取Properties
  4. 第一个 Metro程序(空白应用程序)
  5. POJ2262Goldbach's Conjecture 简单的素数判定
  6. phpnow mysql_使用PHPnow搭建本地PHP环境+创建MySQL数据库 | 倡萌的自留地
  7. github unity 图片切换效果_CSS3图片模糊切换效果
  8. GitHub Pages搭建属于自己的静态网站,并绑定个人域名
  9. 巨杉内核笔记(一)| SequoiaDB 会话(session)简介
  10. 怎样把开启的服务放到后台?