简要讲解Python编程中线程的创建与锁的使用


Posted in Python onFebruary 28, 2016

创建线程
创建线程的两种方法:
1,直接调用threading.Thread来构造thread对象,Thread的参数如下:
class threading.Thread(group=None, target=None, name=None, args=(), kwargs={}) 
group为None;
target为线程将要执行的功能函数;
name为线程的名字,也可以在对象构造后调用setName()来设定;
args为tuple类型的参数,可以为多个,如果只有一个也的使用tuple的形式传入,例如(1,);
kwargs为dict类型的参数,也即位命名参数
threading.Thread对象的其他方法:
start(),用来启动线程;
join(), 等待直到线程结束;
isAlive(),获取线程状态

setDeamon(), 设置线程为deamon线程,必须在start()调用前调用,默认为非demon。
注意: python的主线程在没有非deamon线程存在时就会退出。

threading.currentthread() , 用来获得当前的线程;
threading.enumerate() , 用来多的当前存活的所有线程;

#coding:utf-8
import threading
def func1(num):
 for i in range(num):
  #threading.currentThread()获取当前线程,getName()获取线程名字
  print 'I am %s.num:%s' % (threading.currentThread().getName(), i)
      
def main(thread_num):
 thread_list = [] #定义一个线程列表
 for i in range(thread_num):
  thread_list.append(threading.Thread(target=func1, args = (3, )))
 for a in thread_list:
  #a.setDaemon(True)这个setDaemon默认为False 非守护线程
  #表示主线程等所有子线程结束后,在结束
  #设置为True的话 表示是个守护线程 子线程就会随着主线程的结束而结束
  #听说服务监控工具生成的心跳线程 就是用的守护线程
  a.start()
      
      
 for a in thread_list:
  a.join() #表示等待直到线程运行完毕
      
main(3)

运行结果

I am Thread-1.num:0
I am Thread-1.num:1
I am Thread-1.num:2
I am Thread-2.num:0
I am Thread-2.num:1
I am Thread-2.num:2
I am Thread-3.num:0
I am Thread-3.num:1
I am Thread-3.num:2

2,直接从threading.Thread继承,然后重写__init__方法和run方法

#coding:utf-8
import threading
class MyThread(threading.Thread): #继承父类threading.Thread
 def __init__(self, num ): 
  threading.Thread.__init__(self)
  self.num = num
   
 #把要执行的代码写到run函数里面 线程在创建后会直接运行run函数 
 def run(self):
  for i in range(self.num):
   print 'I am %s.num:%s' % (self.getName(), i)
     
for i in range(3):
 t = MyThread(3)
 t.start()
 t.join()

运行结果

I am Thread-1.num:0
I am Thread-1.num:1
I am Thread-1.num:2
I am Thread-2.num:0
I am Thread-2.num:1
I am Thread-2.num:2
I am Thread-3.num:0
I am Thread-3.num:1
I am Thread-3.num:2

锁的使用
假设我们有一个公共数据x(也可以叫共享资源,临界资源),然后跑10个线程都去访问这变量并对这个变量进行修改的操作,那么就得到意料之外的结果。

import threading       # 导入threading模块
import time        # 导入time模块
class mythread(threading.Thread):  # 通过继承创建类
 def __init__(self,threadname):  # 初始化方法
  # 调用父类的初始化方法
  threading.Thread.__init__(self,name = threadname) 
 def run(self):       # 重载run方法
  global x     # 使用global表明x为全局变量
  for i in range(3):
   x = x + 1
  time.sleep(2)   # 调用sleep函数,让线程休眠5秒
  print x
                
tl = []        # 定义列表
for i in range(10):
 t = mythread(str(i))    # 类实例化
 tl.append(t)      # 将类对象添加到列表中
               
x=0         # 将x赋值为0
for i in tl:
 i.start()       # 依次运行线程

                                                        
运行结果

[root@localhost ~]# python syn.py
30
30
30
30
30
30
30
30
30
30

由于x是全局变量(共享资源),每个线程对x操作后就休眠了
在线程休眠的时候其他线程也都开始执行操作,
最终休眠5秒后x的值最终就被修改为30了

使用互斥锁来保护公共资源。用互斥锁来保证同一时刻只有一个线程访问公共资源,实现简单的同步
互斥锁:threading.Lock 
互斥锁方法:acquire() 获取锁   release():释放锁
当有一个线程获的锁之后,这把锁就会进入locke状态(被锁起来了),另外的线程试图获取锁的时候就会变成同步阻塞状态,
当拥有线程锁的的线程调用锁方法 release()之后就会释放锁,那么锁就会变成开锁unlocked状态,之后再从同步阻塞状态的线程中选择一个来获得锁

import threading       # 导入threading模块
import time        # 导入time模块
class mythread(threading.Thread):     # 通过继承创建类
 def __init__(self,threadname):     # 初始化方法
  threading.Thread.__init__(self,name = threadname) 
 def run(self):       # 重载run方法
  global x      # 使用global表明x为全局变量
  lock.acquire()      # 调用lock的acquire方法
  for i in range(3):
   x = x + 1
  time.sleep(2)   # 调用sleep函数,让线程休眠5秒
  print x
  lock.release()    # 调用lock的release方法
lock = threading.Lock()    # 类实例化
tl = []       # 定义列表
for i in range(10):
 t = mythread(str(i))   # 类实例化
 tl.append(t)    # 将类对象添加到列表中
       
x=0      # 将x赋值为0
for i in tl:
 i.start()      # 依次运行线程

                          
运行结果:

[root@localhost ~]# python syn.py
3
6
9
12
15
18
21
24
27
30

可重入锁:threading.RLock()
方法和互斥锁一样。
假设一个锁嵌套的情况:有个线程以及获取到锁和共享资源了,但是又需要一把锁来获取另外一个资源,那么只要把代码里面的:

lock = threading.Lock()

修改为:

lock = threading.RLock()
Python 相关文章推荐
python根据出生日期获得年龄的方法
Mar 31 Python
Windows下实现Python2和Python3两个版共存的方法
Jun 12 Python
Python的Django框架中的数据库配置指南
Jul 17 Python
Phantomjs抓取渲染JS后的网页(Python代码)
May 13 Python
Python设计模式之迭代器模式原理与用法实例分析
Jan 10 Python
六行python代码的爱心曲线详解
May 17 Python
Django网络框架之创建虚拟开发环境操作示例
Jun 06 Python
对PyQt5中的菜单栏和工具栏实例详解
Jun 20 Python
Python read函数按字节(字符)读取文件的实现
Jul 03 Python
详解scrapy内置中间件的顺序
Sep 28 Python
Python实现FTP文件定时自动下载的步骤
Dec 19 Python
python 办公自动化——基于pyqt5和openpyxl统计符合要求的名单
May 25 Python
Python中time模块和datetime模块的用法示例
Feb 28 #Python
python 写的一个爬虫程序源码
Feb 28 #Python
Python基础语法(Python基础知识点)
Feb 28 #Python
python中map()与zip()操作方法
Feb 27 #Python
python中input()与raw_input()的区别分析
Feb 27 #Python
python PIL模块与随机生成中文验证码
Feb 27 #Python
Pythont特殊语法filter,map,reduce,apply使用方法
Feb 27 #Python
You might like
人族 Terran 基本策略
2020/03/14 星际争霸
PHP 地址栏信息的获取代码
2009/01/07 PHP
深入php函数file_get_contents超时处理的方法详解
2013/06/03 PHP
php读取二进制流(C语言结构体struct数据文件)的深入解析
2013/06/13 PHP
thinkphp模板赋值与替换实例简述
2014/11/24 PHP
WordPress中is_singular()函数简介
2015/02/05 PHP
PHP回调函数与匿名函数实例详解
2017/08/16 PHP
laravel实现查询最后执行的一条sql语句的方法
2019/10/09 PHP
ExtJs3.0中Store添加 baseParams 的Bug
2010/03/10 Javascript
js如何判断用户是否是用微信浏览器
2014/06/05 Javascript
JS实现控制表格行文本对齐的方法
2015/03/30 Javascript
js+canvas绘制五角星的方法
2016/01/28 Javascript
详解Vue2.X的路由管理记录之 钩子函数(切割流水线)
2017/05/02 Javascript
vue params、query传参使用详解
2017/09/12 Javascript
详解使用路由延迟加载 Angular 模块
2017/10/12 Javascript
ES6解构赋值实例详解
2017/10/31 Javascript
Vue-不允许嵌套式的渲染方法
2018/09/13 Javascript
在JavaScript中实现链式调用的实现
2019/12/24 Javascript
JS动态图片的实现方法完整示例
2020/01/13 Javascript
js实现超级玛丽小游戏
2020/03/18 Javascript
[52:52]完美世界DOTA2联赛PWL S3 LBZS vs access 第一场 12.10
2020/12/13 DOTA
Python实现建立SSH连接的方法
2015/06/03 Python
python交互式图形编程实例(三)
2017/11/17 Python
Python使用Matplotlib实现雨点图动画效果的方法
2017/12/23 Python
python中文编码与json中文输出问题详解
2018/08/24 Python
Python中__slots__属性介绍与基本使用方法
2018/09/05 Python
python版飞机大战代码分享
2018/11/20 Python
Python求平面内点到直线距离的实现
2020/01/19 Python
django 模型字段设置默认值代码
2020/07/15 Python
G-Form护具官方网站:美国运动保护装备
2019/09/04 全球购物
求最大连续递增数字串(如"ads3sl456789DF3456ld345AA"中的"456789")
2015/09/11 面试题
小学毕业典礼演讲稿
2014/09/09 职场文书
武当山导游词
2015/02/03 职场文书
2016年大学生实习单位评语
2015/12/01 职场文书
python之np.argmax()及对axis=0或者1的理解
2021/06/02 Python
Unity连接MySQL并读取表格数据的实现代码
2021/06/20 MySQL