python-day36--并发编程之多线程

十三、死锁、递归锁

  1.所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁

 1 from threading import Lock,Thread
 2 import time
 3 mutexB=Lock()
 4 mutexA=Lock()
 5 class MyThread(Thread):
 6     def run(self):
 7         self.f1()
 8         self.f2()
 9
10     def f1(self):
11         mutexA.acquire()
12         print(‘%s拿到了A锁‘ %self.name)
13         mutexB.acquire()
14         print(‘%s拿到了B锁‘ %self.name)
15         mutexB.release()
16         mutexA.release()
17
18     def f2(self):
19         mutexB.acquire()
20         print(‘%s拿到了B锁‘ %self.name)
21         time.sleep(1)
22         mutexA.acquire()
23         print(‘%s拿到了A锁‘ %self.name)
24         mutexA.release()
25         mutexB.release()
26
27 if __name__ == ‘__main__‘:
28     for i in range(10):
29         t=MyThread()
30         t.start()
31
32 # 结果
33 # Thread-1拿到了A锁
34 # Thread-1拿到了B锁
35 # Thread-1拿到了B锁
36 # Thread-2拿到了A锁
37 。。。。 卡住了

  2.解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。

这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁:

 1 from threading import Thread,RLock
 2 import time
 3 mutexB=mutexA=RLock()
 4 class MyThread(Thread):
 5     def run(self):
 6         self.f1()
 7         self.f2()
 8
 9     def f1(self):
10         mutexA.acquire()
11         print(‘\033[32m%s 拿到A锁‘ %self.name)
12         mutexB.acquire()
13         print(‘\033[45m%s 拿到B锁‘ %self.name)
14         mutexB.release()
15         mutexA.release()
16
17     def f2(self):
18         mutexB.acquire()
19         print(‘\033[32m%s 拿到B锁‘ %self.name)
20         time.sleep(1)
21         mutexA.acquire()
22         print(‘\033[45m%s 拿到A锁‘ %self.name)
23         mutexA.release()
24         mutexB.release()
25
26 if __name__ == ‘__main__‘:
27     for i in range(2):
28         t=MyThread()
29         t.start()
30
31 # 结果:
32 # Thread-1 拿到A锁
33 # Thread-1 拿到B锁
34 # Thread-1 拿到B锁
35 # Thread-1 拿到A锁
36 # Thread-2 拿到A锁
37 # Thread-2 拿到B锁
38 # Thread-2 拿到B锁
39 # Thread-2 拿到A锁

十四、信号量Semaphore

  Semaphore管理一个内置的计数器,
  每当调用acquire()时内置计数器-1;
  调用release() 时内置计数器+1;
  计数器不能小于0;当计数器为0时,acquire()将阻塞线程直到其他线程调用release()。

 1 from threading import Thread,Semaphore,currentThread
 2 import time,random
 3 sm=Semaphore(5)    #限制最大连接数为5
 4 def task():
 5     sm.acquire()
 6     print(‘%s 上厕所‘ %currentThread().getName())
 7     time.sleep(random.randint(1,3))
 8     print(‘%s 走了‘ %currentThread().getName())
 9     sm.release()
10 if __name__ == ‘__main__‘:
11     for i in range(20):
12         t=Thread(target=task)
13         t.start()

  与进程池是完全不同的概念,进程池Pool(4),最大只能产生4个进程,而且从头到尾都只是这    四个进程,不会产生新的,而信号量是产生一堆线程/进程

十五、Event事件

1 event.isSet():返回event的状态值;
2
3 event.wait():如果 event.isSet()==False将阻塞线程;
4
5 event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;
6
7 event.clear():恢复event的状态值为False。

 1 from threading import Thread,Event,currentThread
 2 import time
 3 e=Event()
 4
 5 def traffic_lights():
 6     time.sleep(5)
 7     e.set()
 8
 9 def car():
10     print(‘\033[45m%s 等‘ %currentThread().getName())
11     e.wait()
12     print(‘\033[45m%s 跑‘ %currentThread().getName())
13
14
15 if __name__ == ‘__main__‘:
16     for i in range(10):
17         t=Thread(target=car)
18         t.start()
19     traffic_thread=Thread(target=traffic_lights)
20     traffic_thread.start()

例子

 1 from threading import Thread,Event,currentThread
 2 import time
 3 e=Event()
 4 def conn_mysql():
 5     count=1
 6     while not e.is_set():
 7         if count > 3:
 8             raise ConnectionError(‘尝试链接的次数过多‘)
 9         print(‘\033[45m%s 第%s次尝试‘ %(currentThread().getName(),count))
10         e.wait(timeout=1)
11         count+=1
12     print(‘\033[45m%s 开始链接‘ %currentThread().getName())
13
14 def check_mysql():
15     print(‘\033[45m%s 检测mysql...‘ %currentThread().getName())
16     time.sleep(4)     #超时了
17     e.set()
18 if __name__ == ‘__main__‘:
19     t=Thread(target=check_mysql)
20     t.start()
21     for i in range(3):
22         t=Thread(target=conn_mysql)
23         t.start()

重要的例子

十六、定时器

1 from threading import Timer
2
3 def hello(n):
4     print("hello, world",n)
5
6 t = Timer(3, hello,args=(123,))   #3秒后运行hello函数, 可以传参数
7 t.start()

十七、线程queue

  queue队列 :使用import queue,用法与进程Queue一样

  queue.Queue      #先进先出   #队列

 1 import queue
 2
 3 q=queue.Queue()
 4 q.put(‘first‘)
 5 q.put(‘second‘)
 6 q.put(‘third‘)
 7
 8 print(q.get())
 9 print(q.get())
10 print(q.get())
11 ‘‘‘
12 结果(先进先出):
13 first
14 second
15 third
16 ‘‘‘

  queue.LifoQueue     #last in fisrt out  #堆栈

 1 import queue
 2
 3 q=queue.LifoQueue()
 4 q.put(‘first‘)
 5 q.put(‘second‘)
 6 q.put(‘third‘)
 7
 8 print(q.get())
 9 print(q.get())
10 print(q.get())
11 ‘‘‘
12 结果(后进先出):
13 third
14 second
15 first
16 ‘‘‘

  queue.PriorityQueue     #存储数据时可设置优先级的队列

 1 import queue
 2
 3 q=queue.PriorityQueue()
 4 #put进入一个元组,元组的第一个元素是优先级(通常是数字,也可以是非数字之间的比较),数字越小优先级越高
 5 q.put((20,‘a‘))
 6 q.put((10,‘b‘))
 7 q.put((30,‘c‘))
 8
 9 print(q.get())
10 print(q.get())
11 print(q.get())
12 ‘‘‘
13 结果(数字越小优先级越高,优先级高的优先出队):
14 (10, ‘b‘)
15 (20, ‘a‘)
16 (30, ‘c‘)
17 ‘‘‘

时间: 2024-10-29 19:07:30

python-day36--并发编程之多线程的相关文章

python 学习_第四模块 并发编程(多线程)

python 学习_第四模块 并发编程(多线程) 1  开启线程方式 from threading import Thread import time def say(name): time.sleep(2) print("%s hello"%name) if __name__ =="__main__": t = Thread(target=say,args=("alex",)) t.start() print("主线程")

Python并发编程04/多线程

目录 Python并发编程04/多线程 1.生产消费者模型 2.线程的理论知识 2.1什么是线程 2.2线程vs进程 2.3线程的应用 3.开启进程的两种方式 3.1第一种方式 3.2第一种方式 4.线程vs进程的代码对比 4.1开启速度对比 4.2对比pid 4.3同一个进程内线程共享内部数据 5.线程的其他方法 6.join与守护线程 6.1join 6.2守护线程 7.互斥锁 Python并发编程04/多线程 1.生产消费者模型 #编程思想,模型,设计模式,理论等等,都是交给你一种编程的方

Python 3 并发编程多进程之队列(推荐使用)

Python 3 并发编程多进程之队列(推荐使用) 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的. 可以往队列里放任意类型的数据 创建队列的类(底层就是以管道和锁定的方式实现): 1 Queue([maxsize]):创建共享的进程队列,Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递. 参数介绍: 1 maxsize是队列中允许最大项数,省略则无大小限制. 方法介绍: 1.主要

并发编程之多线程

一.并发编程之多线程 1.线程简单介绍 进程是资源单位,把所有资源集中到一起,而线程是执行单位,真正执行的是线程 每个进程都有一个地址空间,而且默认就有一个控制线程 多线程:在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间.进程之间是竞争关系,线程之间是协作关系 线程的创建开销比进程小很多,运行较快 主线程从执行层面上代表了其所在进程的执行过程 2.线程开启方式 方式一:使用替换threading模块提供的Thread from threading import Thread  d

python之并发编程

一.操作系统 1.概念 操作系统就是一个协调.管理和控制计算机硬件资源和软件资源的控制程序,操作系统位于计算机硬件与应用软件之间,本质也是一个软件. 操作系统由操作系统的内核(运行于内核态,管理硬件资源)以及系统调用(运行于用户态,为应用程序员写的应用程序提供系统调用接口)两部分组成 现代计算机或者网络都是多用户的,多个用户不仅共享硬件,而且共享文件,数据库等信息,共享意味着冲突和无序. 2.操作系统功能 1.记录哪个程序使用什么资源 2.对资源请求进行分配 3.为不同的程序和用户调解互相冲突的

day10-python并发编程之多线程协程及MySQL

第1章 python并发编程之多线程 1.1 死锁现象与递归锁 1.1.1 死锁概念 进程也有死锁与递归锁,在进程那里忘记说了,放到这里一切说了额 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁 1.1.2 博客实例 from threading import Thread,Lock import time mutexA=L

Python 3 并发编程多进程之进程同步(锁)

Python 3 并发编程多进程之进程同步(锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,竞争带来的结果就是错乱,如何控制,就是加锁处理. 1.多个进程共享同一打印终端 from multiprocessing import Process import os,time def work(): print('%s is running' %os.getpid()) time.sleep(2) print('%s is done' %os.g

Java并发编程之多线程同步

线程安全就是防止某个对象或者值在多个线程中被修改而导致的数据不一致问题,因此我们就需要通过同步机制保证在同一时刻只有一个线程能够访问到该对象或数据,修改数据完毕之后,再将最新数据同步到主存中,使得其他线程都能够得到这个最新数据.下面我们就来了解Java一些基本的同步机制. Java提供了一种稍弱的同步机制即volatile变量,用来确保将变量的更新操作通知到其他线程.当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的.然而,在访问volatile变量时不会执行加锁操作

使用Python进行并发编程

让计算机程序并发的运行是一个经常被讨论的话题,今天我想讨论一下Python下的各种并发方式. 并发方式 线程(Thread) 多线程几乎是每一个程序猿在使用每一种语言时都会首先想到用于解决并发的工具(JS程序员请回避),使用多线程可以有效的利用CPU资源(Python例外).然而多线程所带来的程序的复杂度也不可避免,尤其是对竞争资源的同步问题. 然而在python中由于使用了全局解释锁(GIL)的原因,代码并不能同时在多核上并发的运行,也就是说,Python的多线程不能并发,很多人会发现使用多线

python中并发编程基础1

并发编程基础概念 1.进程. 什么是进程? 正在运行的程序就是进程.程序只是代码. 什么是多道? 多道技术: 1.空间上的复用(内存).将内存分为几个部分,每个部分放入一个程序,这样同一时间在内存中就有了多道程序. 2.时间上的复用(CPU的分配).只有一个CPU,如果程序在运行过程中遇到了I/O阻塞或者运行时间足够长.操作系统会按照算法将CPU分配给其他程序使用,依次类推.直到第一个程序被重新分配到CPU会继续运行. 多道技术中的问题解决: 空间复用:程序之间的内存必须分割.这种分割需要在硬件