一,开启线程的两种方式

方法一:

from threading import Thread
import random,time
def eat(name):
print('%s is eating......'%name)
time.sleep(random.randint(1,5))
print('%s had end....'%name)
if __name__ == '__main__':
t=Thread(target=eat,args=('xiaoming',))#创建线程
t.start() #开启线程
print('主线程')

方法二:

from threading import Thread
import random,time
class Eat(Thread):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
print('%s is eating......' % self.name)
time.sleep(random.randint(6, 15))
print('%s had end....' % self.name)
if __name__ == '__main__':
t=Eat('xiaoming')
t.start()
print('主线程')

二,线程相关的其他方法

Thread实例对象的方法
# isAlive(): 返回线程是否活动的。
# getName(): 返回线程名。
# setName(): 设置线程名。 threading模块提供的一些方法:
# threading.currentThread(): 返回当前的线程变量。
# threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
# threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果

三,守护线程

设置一个线程为守护线程,那么它会等本进程中所有非守护线程运行结束之后才会被主线程给回收,而守护进程会在父进程代码运行完毕

的时候就会被回收。

from threading import Thread,currentThread
import time
def talk1():
print('%s is running'%currentThread().getName())
time.sleep(3)
print('%s is end'%currentThread().getName())
def talk2():
print('%s is running'%currentThread().getName())
time.sleep(3)
print('%s is end'%currentThread().getName()) if __name__ == '__main__':
t1=Thread(target=talk1)
t2=Thread(target=talk2)
t1.daemon=True #设置守护线程
t1.start()
t2.start()
print('主线程')

四,同步锁

1.线程抢的是GIL锁,GIL锁相当于执行权限,拿到执行权限后才能拿到互斥锁Lock,其他线程也可以抢到GIL,但如果发现Lock仍然没有被释放则阻塞,即便是拿到执行权限GIL也要立刻交出来

2.join是等待所有,即整体串行,而锁只是锁住修改共享数据的部分,即部分串行,要想保证数据安全的根本原理在于让并发变成串行,join与互斥锁都可以实现,毫无疑问,互斥锁的部分串行效率要更高
# from threading import Thread,Lock
# import time
# n=100
# def work():
# mutex.acquire()
# global n
# temp=n
# time.sleep(0.1)
# n=temp-1
# mutex.release()
# if __name__ == '__main__':
# mutex=Lock()
# t_l=[]
# for i in range(100):
# t=Thread(target=work)
# t_l.append(t)
# t.start()
# for t in t_l:
# t.join()
# print(n) from threading import Thread,Lock
import time
n=100
def work():
time.sleep(3)
global n
mutex.acquire()
temp=n
time.sleep(0.1)
n=temp-1
mutex.release()
if __name__ == '__main__':
strat=time.time()
mutex=Lock()
t_l=[]
for i in range(100):
t=Thread(target=work)
t_l.append(t)
t.start()
for t in t_l:
t.join()
stop=time.time()
print(n)
print('运行了:%s 秒'%(stop-strat))

互斥锁与join锁

五,死锁现象与递归锁

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

from threading import Thread,Lock
import time
mutexA=Lock()
mutexB=Lock() class MyThread(Thread):
def run(self):
self.func1()
self.func2()
def func1(self):
mutexA.acquire()
print('\033[41m%s 拿到A锁\033[0m' %self.name) mutexB.acquire()
print('\033[42m%s 拿到B锁\033[0m' %self.name)
mutexB.release() mutexA.release() def func2(self):
mutexB.acquire()
print('\033[43m%s 拿到B锁\033[0m' %self.name)
time.sleep(2) mutexA.acquire()
print('\033[44m%s 拿到A锁\033[0m' %self.name)
mutexA.release() mutexB.release() if __name__ == '__main__':
for i in range(10):
t=MyThread()
t.start() '''
Thread-1 拿到A锁
Thread-1 拿到B锁
Thread-1 拿到B锁
Thread-2 拿到A锁
然后就卡住,死锁了
'''

死锁

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

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

from threading import Thread,RLock
import time
mutex=RLock()
class MyThread(Thread): def run(self):
self.func1()
self.func2()
def func1(self):
mutex.acquire()
time.sleep(1)
print('%s 拿到锁'%self.name)
mutex.acquire()
print('%s 拿到锁' % self.name)
mutex.release()
print('%s 释放锁' % self.name)
mutex.release()
print('%s 释放锁' % self.name)
def func2(self):
mutex.acquire() print('%s 拿到锁'%self.name)
mutex.acquire()
print('%s 拿到锁' % self.name)
mutex.release()
print('%s 释放锁' % self.name)
mutex.release()
print('%s 释放锁' % self.name) if __name__ == '__main__': l=[]
for i in range(4):
t = MyThread()
t.start()
l.append(t)
for t in l:
t.join()

递归锁

六,信号量Semaphore

同进程池一样

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

实例:(同时只有5个线程可以获得semaphore,即可以限制最大连接数为5):

from threading import Thread,Semaphore
import threading
import time
# def func():
# if sm.acquire():
# print (threading.currentThread().getName() + ' get semaphore')
# time.sleep(2)
# sm.release()
def func():
sm.acquire()
print('%s get sm' %threading.current_thread().getName())
time.sleep(3)
sm.release()
if __name__ == '__main__':
sm=Semaphore(5)
for i in range(23):
t=Thread(target=func)
t.start()

七,Event

event.isSet():返回event的状态值;

event.wait():如果 event.isSet()==False将阻塞线程;

event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;

event.clear():恢复event的状态值为False。
from threading import Thread,Event,currentThread
import time
e=Event()
def conn_my_sql():
count=1
while not e.is_set():
if count>3:
raise ConnectionError('链接超时')
e.wait(timeout=1)
print('%s 正在进行第%s次链接'%(currentThread().getName(),count))
count+=1
print('链接成功')
def check_my_sql():
print('准备链接.....')
time.sleep(3)
e.set() if __name__ == '__main__':
for i in range(4):
t=Thread(target=conn_my_sql)
t.start()
t=Thread(target=check_my_sql)
t.start()

八,定时器

定时器,指定n秒后执行某操作

from threading import Timer

def hello():
print("hello, world") t = Timer(1, hello)
t.start() # after 1 seconds, "hello, world" will be printed

九,线程Queue

import queue

q=queue.Queue()
q.put('first')
q.put('second')
q.put('third') print(q.get())
print(q.get())
print(q.get())
'''
结果(先进先出):
first
second
third
'''

先进先出,队列形式

import queue

q=queue.LifoQueue()
q.put('first')
q.put('second')
q.put('third') print(q.get())
print(q.get())
print(q.get())
'''
结果(后进先出):
third
second
first
'''

先进后出,堆栈形式

import queue

q=queue.PriorityQueue()
#put进入一个元组,元组的第一个元素是优先级(通常是数字,也可以是非数字之间的比较),数字越小优先级越高
q.put((20,'a'))
q.put((10,'b'))
q.put((30,'c')) print(q.get())
print(q.get())
print(q.get())
'''
结果(数字越小优先级越高,优先级高的优先出队):
(10, 'b')
(20, 'a')
(30, 'c')
'''

指定优先级形式

十,Python标准模块--concurrent.futures

from concurrent.futures import ThreadPoolExecutor
import time,os
def task(n):
print('%s is running'%os.getpid())
time.sleep(2)
return n**2
if __name__ == '__main__':
start=time.time()
p=ThreadPoolExecutor()
l=[]
for i in range(20):
obj=p.submit(task,i)
l.append(obj)
p.shutdown()
print([obj.result() for obj in l])
print(time.time()-start)

ThreadPoolExecutor

from concurrent.futures import ProcessPoolExecutor
import time,random,os
def task(n):
print('%s is running'%os.getpid())
time.sleep(random.randint(1,3))
return n**2 if __name__ == '__main__':
p=ProcessPoolExecutor()
l=[]
for i in range(10):
obj=p.submit(task,i)
l.append(obj)
p.shutdown()
print([obj.result() for obj in l])

ProcessPoolExecutor

python并发编程之多线程二的更多相关文章

  1. Python并发编程04 /多线程、生产消费者模型、线程进程对比、线程的方法、线程join、守护线程、线程互斥锁

    Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线程join.守护线程.线程互斥锁 目录 Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线 ...

  2. python并发编程之多进程(二):互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型

    一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终 ...

  3. 百万年薪python之路 -- 并发编程之 多线程 二

    1. 死锁现象与递归锁 进程也有死锁与递归锁,进程的死锁和递归锁与线程的死锁递归锁同理. 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因为争夺资源而造成的一种互相等待的现象,在无外力的作用 ...

  4. python并发编程之多进程二

    一,multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程.P ...

  5. 29 python 并发编程之多线程理论

    一 什么是线程 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程 车间负责把资源整合 ...

  6. 三 python并发编程之多线程-理论

    一 什么是线程 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程 车间负责把资源整合 ...

  7. python并发编程之多线程理论部分

    阅读目录 一 什么是线程 二 线程的创建开销小 三 线程与进程的区别 四 为何要用多线程 五 多线程的应用举例 六 经典的线程模型(了解) 七 POSIX线程(了解) 八 在用户空间实现的线程(了解) ...

  8. 35、python并发编程之多线程(理论篇)

    一 什么是线程 二 线程的创建开销小 三 线程与进程的区别 四 为何要用多线程 五 多线程的应用举例 六 经典的线程模型(了解) 七 POSIX线程(了解) 八 在用户空间实现的线程(了解) 九 在内 ...

  9. python并发编程之多线程

    一  同步锁 注意: 1线程抢的是GIL锁,GIL锁就是执行权限,拿到权限后才能拿到互斥锁Lock,但是如果发现Lock没有被释放而阻塞,则立即交出拿到的执行权. 2join是等待所有,即整体串行,而 ...

随机推荐

  1. parameterType 和 resultType

    parameterType #{} 和 ${} 1.#{}实现的是向prepareStatement中的预处理语句中设置参数值,sql语句中#{}表示一个占位符即?. 2.使用占位符#{}可以有效防止 ...

  2. PhiloGL学习(1)——场景创建及方块欲露还羞出水面

    前言 上一篇文章中介绍了我认识PhiloGL框架的机缘以及初步的探讨(见JS前端三维地球渲染--中国各城市航空路线展示),在此文中仅仅对此框架进行了简单介绍并初步介绍了一些该框架的知识.首先三维这个东 ...

  3. Hadoop完全分布式环境搭建

    前言 本文搭建了一个由三节点(master.slave1.slave2)构成的Hadoop完全分布式集群(区别单节点伪分布式集群),并通过Hadoop分布式计算的一个示例测试集群的正确性. 本文集群三 ...

  4. linux系统莫名被黑的诡异经历

    2017年10月28日,ssh登录本地虚拟机之后发现主机名被改成了HUAIWEI_P10. 我一个同事用的此款手机,起初怀疑是他,没放心上. 今天(10月30)发现自己ssh登录不上了.恼火了办公室开 ...

  5. [翻译]欢迎来到 C# 7.1

    [翻译]欢迎来到 C# 7.1 原文: Welcome to C# 7.1 在 C# 中,我们一直倾向于主要版本:捆绑了很多功能,并且不太频繁地发布.当我们谈到 C#6.0时,我们甚至还经常忽略掉后面 ...

  6. springmvc+quartz简单实现定时调度

    一.简介:Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用.Quartz可以用来创建简单或为运行十 ...

  7. Hibernate的基础入门(一)

    一Java三层结构 1 web层:struts框架 2 service层:Spring框架 3  dao层 :hibernate框架 相当于MVC的思想 1 M:模型èhibernate框架 2 V: ...

  8. 基于HTML5 Canvas的CSG构造实体几何书架

    CSG 构造实体几何这个概念在工业水利水电施工上.游戏上已经有很多人使用了,最简单的实体表示叫作体元,通常是形状简单的物体,如立方体.圆柱体.棱柱.棱锥.球体.圆锥等.根据每个软件包的不同这些体元也有 ...

  9. windows下配置wampserver

    第一,打开局域网访问 配置文件:点击右下角的WAMP 服务器小托盘,选择Apache>httpd.conf 搜索关键字 "deny from ",会发现一处 "de ...

  10. WebService--jax

    使用javax.jws编写webservice服务: 服务端: 1,定义webservice接口: package com.jws.serviceInterface; import javax.jws ...