转自:https://www.cnblogs.com/chengd/articles/7770898.html

1. threading.Lock()

import threading

balance = 0
lock = threading.Lock() def change_it(n):
# 先存后取,结果应该为0:
global balance
balance = balance + n
balance = balance - n def run_thread(n):
for i in range(100000):
# 先要获取锁:
lock.acquire()
try:
# 放心地改吧:
change_it(n)
finally:
# 改完了一定要释放锁:
lock.release() if __name__ == "__main__":
t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
print(balance)

当多个线程同时执行lock.acquire()时,只有一个线程能成功地获取锁,然后继续执行代码,其他线程就继续等待直到获得锁为止。

获得锁的线程用完后一定要释放锁,否则那些苦苦等待锁的线程将永远等待下去,成为死线程。所以我们用try...finally来确保锁一定会被释放。

2、threading.Rlock()

RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。注意:如果使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的锁。

import threading

# Lock对象
lock = threading.Lock() def test1():
lock.acquire()
lock.acquire()
# 产生了死琐。
print("test1")
lock.release()
lock.release() # RLock对象
rLock = threading.RLock() def test2():
rLock.acquire()
rLock.acquire()
# 在同一线程内,程序不会堵塞。
print("test2")
rLock.release()
rLock.release() if __name__ == "__main__":
t1 = threading.Thread(target=test1, args=())
t2 = threading.Thread(target=test2, args=())
t1.start()
t2.start() t2.join()
t1.join()

RLock允许嵌套。

def run1():
print("grab the first part data")
lock.acquire()
global num
num +=1
lock.release()
return num
def run2():
print("grab the second part data")
lock.acquire()
global num2
num2+=1
lock.release()
return num2
def run3():
lock.acquire()
res = run1()
print('--------between run1 and run2-----')
res2 = run2()
lock.release()
print(res,res2)   = threading.Thread(target=run3)
  t.start()

3. threading.active_count() 返回当前存活的线程对象的数量

通过计算len(threading.enumerate())长度而来

4. threading.current_thread() 返回当前线程对象

import time
import threading def run():
thread = threading.current_thread()
print('%s is running...'% thread.getName()) #返回线程名称
time.sleep(10) #休眠10S方便统计存活线程数量 if __name__ == "__main__":
#设置thread的名称
t = threading.Thread(target=run, name="test_thread")
t.start() print('%s is running...' % threading.current_thread().getName())
print("thread count:%d" % threading.active_count())
print("thread count:%d" % len(threading.enumerate())) t.join()

5. threading.enumerate()返回当前存在的所有线程对象的列表

6.threading.get_ident() 返回线程pid

7. threading.main_thread()

import time
import threading def run():
print("get the main_thread name is %s" % threading.main_thread().getName())
print("pid:%s" % threading.get_ident())
print('ThreadName is :%s' % threading.enumerate()) # 返回所有线程对象列表
time.sleep(10) if __name__ == "__main__":
#设置thread的名称
t = threading.Thread(target=run, name="test_thread")
t.start() t.join()

8. threading.Condition()

可以把Condiftion理解为一把高级的锁,它提供了比Lock, RLock更高级的功能,允许我们能够控制复杂的线程同步问题。

threadiong.Condition在内部维护一个锁对象(默认是RLock,可被多次acquire),可以在创建Condigtion对象的时候把锁对象作为参数传入。

Condition也提供了acquire, release方法,其含义与锁的acquire, release方法一致,其实它只是简单的调用内部锁对象的对应的方法而已。

Condition还提供wait方法、notify方法、notifyAll方法(特别要注意:这些方法只有在占用锁(acquire)之后才能调用,否则将会报RuntimeError异常。)

wait([timeout]):线程挂起,直到收到一个notify通知或者超时(可选的,浮点数,单位是秒s)才会被唤醒继续运行。

wait()必须在已获得锁前提下才能调用,否则会触发RuntimeError。调用wait()会释放锁,直至该线程被Notify()、NotifyAll()或者超时线程又重新获得锁.

notify(n=1):通知其他线程,那些挂起的线程接到这个通知之后会开始运行,默认是通知一个正等待该condition的线程,最多则唤醒n个等待的线程。

notify()必须在已获得锁前提下才能调用,否则会触发RuntimeError。notify()不会主动释放锁。

notifyAll(): 如果wait状态线程比较多,notifyAll的作用就是通知所有线程(这个一般用得少)(不知道是否会产生线程惊群)

捉迷藏的游戏:

一个藏(Hider),一个找(Seeker)

戏的规则如下:

cond = threading.Condition()

1. 游戏开始之后,Seeker加锁cond.acquire(),蒙上眼睛后 cond.notify() 通知Hider已经蒙眼,

2. 游戏开始之后,Hider加锁cond.acquire(),cond.wait() 等待Seeker的通知(已经蒙眼),

3. Hider收到Seeker蒙眼通知之后,进行躲藏,在完成躲藏之后cond.notify()通知Seeker已经躲藏好,并cond.wait()等待Seeker找到他的通知

4、Seeker接收到通知(Hider完成躲藏)之后,就开始找Hider,并在找到Hider向Hider发出通知cond.notify()

问题!!!如果超过1分钟没有找到躲藏者,判Seeker输,怎么弄?

尝试,cond.wait(60) 加上使用一个全局bool类型的值,结果发现cond.wait(60)在超时之后并不会唤醒,不知道是什么原因,我的测试环境是Windows

import time
import threading def Seeker(cond, name):
time.sleep(2)
cond.acquire()#可多次acquire
print('%s :我已经把眼睛蒙上了!'% name)
cond.notify()
cond.wait()
for i in range(3):
print('%s is finding!!!'% name)
time.sleep(2)
print("yeah, find the hider")
cond.notify()
cond.release()
print('%s :我赢了!'% name) def Hider(cond, name):
cond.acquire()
cond.wait()
for i in range(2):
print('%s is hiding!!!'% name)
time.sleep(3)
print('%s :我已经藏好了,你快来找我吧!'% name)
cond.notify()
cond.wait()
cond.release()
print('%s :被你找到了,唉~^~!'% name) if __name__ == "__main__":
cond = threading.Condition()
seeker = threading.Thread(target=Seeker, args=(cond, 'seeker'))
hider = threading.Thread(target=Hider, args=(cond, 'hider'))
seeker.start()
time.sleep(0.1)
hider.start()

9. threading.Semaphore和BoundedSemaphore

Semaphore:Semaphore 在内部管理着一个计数器。

调用 acquire() 会使这个计数器 -1,release() 则是+1(可以多次release(),所以计数器的值理论上可以无限).计数器的值永远不会小于 0,当计数器到 0 时,再调用 acquire() 就会阻塞,直到其他线程来调用release()

BoundedSemaphore:类似于Semaphore;不同在于BoundedSemaphore 会检查内部计数器的值,并保证它不会大于初始值,如果超了,就引发一个 ValueError。

多数情况下,semaphore 用于守护限制访问(但不限于 1)的资源,如果 semaphore 被 release() 过多次,这意味着存在 bug

import time
import threading def run(n):
# 获得信号量,信号量减一
semaphore.acquire()
time.sleep(1)
print("run the thread: %s" % n) # 释放信号量,信号量加一
semaphore.release()
#semaphore.release() # 可以多次释放信号量,每次释放计数器+1
#semaphore.release() # 可以多次释放信号量,每次释放计数器+1 if __name__ == "__main__":
semaphore = threading.Semaphore(2)#semaphore计数器初始化为2 for i in range(10):
t = threading.Thread(target=run, args=(i,))
t.start() while threading.active_count() != 1:
time.sleep(0.1)
else:
print('----all threads done---') print("----------main thread finish-----------")
import time
import threading def run(n):
# 获得信号量,信号量减一
semaphore.acquire()
time.sleep(1)
print("run the thread: %s" % n) # 释放信号量,信号量加一
try:
semaphore.release()
except ValueError as e:
print(e) if __name__ == "__main__":
semaphore = threading.BoundedSemaphore(2)#内部计数器的初始值,后续操作不允许计数器超过初始值 for i in range(10):
t = threading.Thread(target=run, args=(i,))
t.start() while threading.active_count() != 1:
time.sleep(0.1)
else:
print('----all threads done---') print("----------main thread finish-----------")

Python线程二的更多相关文章

  1. Python 多线程 使用线程 (二)

    Python中实现多线程需要使用到 threading 库,其中每一个 Thread类 的实例控制一个线程. Thread类 #类签名 def __init__(self, group=None, t ...

  2. python基础(34):线程(二)

    1. python线程 1.1 全局解释器锁GIL Python代码的执行由Python虚拟机(也叫解释器主循环)来控制.Python在设计之初就考虑到要在主循环中,同时只有一个线程在执行.虽然 Py ...

  3. [python] 线程简介

    参考:http://www.cnblogs.com/aylin/p/5601969.html 我是搬运工,特别感谢张岩林老师! python 线程与进程简介 进程与线程的历史 我们都知道计算机是由硬件 ...

  4. python线程同步原语--源码阅读

    前面两篇文章,写了python线程同步原语的基本应用.下面这篇文章主要是通过阅读源码来了解这几个类的内部原理和是怎么协同一起工作来实现python多线程的. 相关文章链接:python同步原语--线程 ...

  5. Python 线程和进程

    一.什么是线程 1.线程是操作系统能够进行运算调度的最小单位.它被包含在进程中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务 ...

  6. Python学习——Python线程

    一.线程创建 #方法一:将要执行的方法作为参数传给Thread的构造方法 import threading import time def show(arg): time.sleep(2) print ...

  7. python 线程 进程

    1.进程与线程优.缺点的比较总言:使用进程和线程的目的,提高执行效率. 进程: 优点:能利用机器的多核性能,同时进行多个操作. 缺点:需要耗费资源,重新开辟内存空间,耗内存. 线程: 优点:共享内存( ...

  8. python 线程、多线程

    复习进程知识: python:主进程,至少有一个主线程 启动一个新的子进程:Process,pool 给每一个进程设定一下执行的任务:传一个函数+函数的参数 如果是进程池:map函数:传入一个任务函数 ...

  9. python 线程 进程 协程 学习

    转载自大神博客:http://www.cnblogs.com/aylin/p/5601969.html 仅供学习使用···· python 线程与进程简介 进程与线程的历史 我们都知道计算机是由硬件和 ...

随机推荐

  1. js,jq获取父,兄弟,子节点整理

    js获取节点 父: parentNode 获取已知节点的父节点. 子: childNodes; 得到全部子节点 children 得到全部子节点 firstChild 获得第一个子节点 lastChi ...

  2. python的json模块的dumps,loads,dump,load方法介绍

    dumps和loads方法都在内存中转换, dump和load的方法会多一个步骤,dump是把序列化后的字符串写到一个文件中,而load是从一个文件中读取字符串 将列表转为字符串 >>&g ...

  3. python 获取进程数据

    from multiprocessing import Process, Manager def func(dt, lt): ): key = 'arg' + str(i) dt[key] = i * ...

  4. 【C#】侦听文件系统更改通知 FileSystemWatcher 类

    using System; using System.IO; using System.Security.Permissions; public class Watcher { public stat ...

  5. 幂率定律及绘制Power-law函数

    来自:Eastmount 在我们日常生活中Power Law(幂次分布,Power-law Distributions)是常见的一个数学模型,如二八原则.这个世界上是20%的人掌握80%的人的金钱去经 ...

  6. Array、List和ArrayList的区别(推荐: 浅显易懂)

    数组.List和ArrayList的区别(推荐: 浅显易懂)   有些知识点可能平时一直在使用,不过实际开发中我们可能只是知其然不知其所以然,所以经常的总结会对我们的提高和进步有很大的帮助,这里记录自 ...

  7. 力扣(LeetCode)500. 键盘行

    给定一个单词列表,只返回可以使用在键盘同一行的字母打印出来的单词.键盘如下图所示. 示例: 输入: ["Hello", "Alaska", "Dad& ...

  8. 基于python Arcface 实现人脸检测和识别

    虹软的人脸识别技术也是很强的,重要的是他免费提供了离线的sdk,还提供了实例,这个是目前几家研究人脸识别的大公司里面少有的.识别能力正常用还是可以的.我这个代码是调用的离线sdk实现的 ``` fro ...

  9. Python Scrapy 爬取煎蛋网妹子图实例(一)

    前面介绍了爬虫框架的一个实例,那个比较简单,这里在介绍一个实例 爬取 煎蛋网 妹子图,遗憾的是 上周煎蛋网还有妹子图了,但是这周妹子图变成了 随手拍, 不过没关系,我们爬图的目的是为了加强实战应用,管 ...

  10. JS中如何生成全局变量

    JS中如何生成全局变量 一.总结 一句话总结:在函数内部,一般用var声明的为局部变量,没用var声明的一般为全局变量 在函数内没用var声明的一般为全局变量 1.js中的函数中的this指向的是谁? ...