Python 基础入门 10_3 进程线程和协程

摘要:
由于运行过程中出现异常,将完成销毁或退出信号量()和屏障()的实现:当这五个线程执行函数时,它们遇到信号量或屏障函数,而剩下的两个线程只能在这三个线程完成执行后才能跨过此通道。然后创建两个线程来执行函数num=0deftestRun(num2):当第一个线程刚刚执行num+=num2时,第二个线程已经执行num+=num2,
"""
线程一共有5个状态:创建,就绪/可运行状态,运行,阻塞/等待,完成/死亡
当线程创建出来后,就进入了可运行状态,等线程启动后,便到了运行阶段,运行完后,便会完成销毁或者运行的过程中异常导致中途退出
Semaphore()和Barrier()的实现:
上述代码我们同时创建了5个线程并启动,这5个线程执行函数时,遇到了Semaphore或Barrier的函数,Semaphore相当于只有3个通道,5个线程
遇到3个通道,这能是最快的3个线程过这三个通过,剩余的两个线程等待这三个线程执行完后才能过这个通道。而Barrier相当于只有1个通道,
但这个通道规定,必须三个线程同时通过,当5个线程来到这个通道,最快的三个线程组成一队进入这个通过,而后来的两个线程则一直在等待
前三个线程执行完毕,并等待另外一个线程的到来才能组队通过通道

为什么需要让线程等待? 除了我们控制并发数和组合数之外,等待的另外一个作用是在线程间交互中保持数据的准确性
"""
#举例:我们有一个函数,一个全局变量,函数的内容是多次循环对这个全局变量加一个定制数,在减去这个指定数,然后创建两个线程去执行这个函数
num = 0
def testRun(num2):
global num
for i in range(10000000):
num += num2
num -= num2
#
# if __name__ == "__main__":
# t1 = threading.Thread(target=testRun,args=(6,))
# t2 = threading.Thread(target=testRun,args=(6,))
# t1.start(),t2.start()
# t1.join(),t1.join()
# print("num:",num)

"""
执行后发现:有时候结果是0,而有时候结果是6,其原因是,线程是并发运行的,我们不知道那个线程快,那个线程慢,
当第一个线程刚执行num += num2,还未来的及执行num -= num2时,第二个线程已经执行了num += num2,周而复始,等两个线程执行完后,
便出来结果可能不为0的结果

要解决结果,就需要让其中一个线程等待另外一个线程执行完一次后在执行,保证他们执行完一次后结果为0
有几种方法可以做到:
1.添加锁,这种方式阻止了多线程的并发,让多线程暂时的变成单线程执行,效率大大降低,同时,若每个线程都有自己的锁,
当这个线程加锁,之后异常出错后,这个线程就被清理调用,但锁没有被开,其他的线程一直等待锁的解开,便造成了死锁,
锁的创建: threading.Lock()
如下:
"""
import threading
lock = threading.Lock()
num = 0
def run(n):
global num
for i in range(100000000):
# lock.acquire() #加锁
# try: #捕获异常,避免出现死锁
# num = num + n
# num = num - n
# finally:
# lock.release() #解锁
#锁的另外一种形式:自动上锁和解锁,可以减低死锁的概率
with lock:
num = num + n
num = num - n

# if __name__ == "__main__":
# t1 = threading.Thread(target=run,args=(6,))
# t2 = threading.Thread(target=run,args=(6,))
# t1.start(),t2.start()
# t1.join(),t1.join()
# print("num:",num)

"""
2.将全局变量变成线程的局部变量,这样每个线程有自己的局部变量,同时自己的局部变量在其他地方是调用不了,这样也确保了数据的准确性
如下:
"""
local = threading.local() #创建线程局部变量空间
num = 0
# def run(x,n):
# x = x + n
# x = x - n

def func(n):
local.x = num
for i in range(100000000):
local.x += n
local.x -= n
print("%s-%d" %(threading.current_thread().name,local.x))

# if __name__ == "__main__":
# t1 = threading.Thread(target=func,args=(6,))
# t2 = threading.Thread(target=func,args=(6,))
# t1.start(),t2.start()
# t1.join(),t1.join()

免责声明:文章转载自《Python 基础入门 10_3 进程线程和协程》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Ubuntu 14.04 安装Visual studio CodeHadoop配置项整理(hdfs-site.xml)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

windows时间函数

介绍        我们在衡量一个函数运行时间,或者判断一个算法的时间效率,或者在程序中我们需要一个定时器,定时执 行一个特定的操作,比如在多媒体中,比如在游戏中等,都会用到时间函数。还比如我们通过记录函数或者算法开始和截至的时间,然后利用两者之差得出函数或者 算法的运行时间。编译器和操作系统为我们提供了很多时间函数,这些时间函数的精度也是各不相同的,所以...

如何终止java线程

终止线程的三种方法      有三种方法可以使终止线程。      1.  使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。      2.  使用stop方法强行终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果)。      3.  使用interrupt方法中断线程。  1. 使用...

Java回调实现异步 (转)

出处: Java回调实现异步   在正常的业务中使用同步线程,如果服务器每处理一个请求,就创建一个线程的话,会对服务器的资源造成浪费。因为这些线程可能会浪费时间在等待网络传输,等待数据库连接等其他事情上,真正处理业务逻辑的时间很短很短,但是其他线程在线程池满了之后又会阻塞,等待前面的线程处理完成。而且,会出现一个奇怪的现象,客户端的请求被阻塞,但是cpu的...

理解杀进程的实现原理

copy from : http://gityuan.com/2016/04/16/kill-signal/ 基于Android 6.0的源码剖析, 分析kill进程的实现原理,以及讲讲系统调用(syscall)过程,涉及源码: /framework/base/core/java/android/os/Process.java /framework/bas...

winform进程、线程

随笔- 86 文章- 0 评论- 0 winform进程、线程 进程: 一般来说,一个程序就是一个进程,不过也有一个程序需要多个进程支持的情况。 进程所使用的类:Process 所需命名空间:System.Diagnostics; 可以通过进行来开启计算机上现有的程序: 1、使用静态方法Start();但必须要知道进程名 2、也可以实例化对象,来调用S...

Java经典练习题_Day03

一、选择 B D(死循环) E(switch) BC 二、编程 1、读入一个整数,表示一个人的年龄。 如果小于6岁,则输出“儿童”, 6岁到13岁,输出“少儿”; 14岁到18岁,输出“青少年”; 18岁到35岁,输出“青年”; 35岁到50岁,输出“中年”; 50 岁以上输出“中老年”。 import java.util.*; /* * 读入一个整数...