当你知道锁的使用抢锁必须要释放锁,其实你在操作锁的时候也极其容易产生死锁现象(整个程序卡死 阻塞)
from threading import Thread, Lock
import time
mutexA = Lock()
mutexB = Lock()
# 类只要加括号多次 产生的肯定是不同的对象
# 如果你想要实现多次加括号等到的是相同的对象 单例模式
class MyThead(Thread):
def run(self):
self.func1()
self.func2()
def func1(self):
mutexA.acquire()
print('%s 抢到A锁'% self.name) # 获取当前线程名
mutexB.acquire()
print('%s 抢到B锁'% self.name)
mutexB.release()
mutexA.release()
def func2(self):
mutexB.acquire()
print('%s 抢到B锁'% self.name)
time.sleep(2)
mutexA.acquire()
print('%s 抢到A锁'% self.name) # 获取当前线程名
mutexA.release()
mutexB.release()
if __name__ == '__main__':
for i in range(10):
t = MyThead()
t.start()
递归锁的特点:
可以被连续的acquire和release
但是只能被第一个抢到这把锁执行上述操作
它的内部有一个计数器 每acquire一次计数加一 每realse一次计数减一
只要计数不为0 那么其他人都无法抢到该锁
# 代码只需要将上述死锁的
mutexA = Lock()
mutexB = Lock()
# 换成
mutexA = mutexB = RLock()
# 这样死锁的程序就可以正常运行下去
信号量在不同阶段可能对应不同的技术点,在并发编程中,信号量指的是锁!!
信号量与互斥锁的比较:信号量可以看成是多个坑位,互斥锁只能是一个坑位!!
信号量的具体语法:
from threading import Thread, Semaphore # 信号量的模块
import time,random
sm = Semaphore(5) # 表示同时开设5个坑位(互斥锁只开设一个)
def task(name):
sm.acquire() # 加锁
print('%s正在蹲坑'%name)
time.sleep(random.randint(1,3)) # 蹲坑时间不等
sm.release() # 释放锁
if __name__ == '__main__':
for i in range(20): # 20个人去抢5个厕所
t = Thread(target=task,args=(i,))
t.start()
主进程/线程等待子进程/线程运行结束时,我们使用的是join方法!
而需要子进程/线程之间的相互的等待结束,需要用到event事件
from threading import Thread,Event
import time
# 1.先产生一个event对象
event = Event()
def person():
print('你来了')
time.sleep(2)
event.set() # 2.发送信号,表示我执行完毕了,你可以结束了
def my():
event.wait() # 3.接收到信号,好的我开始执行
print('我走了')
if __name__ == '__main__':
t = Thread(target=person)
t1 = Thread(target=my)
t1.start()
t.start()
池是用来保证计算机硬件安全的情况下最大限度的利用计算机,它降低了程序运行的效率但是保证了计算机硬件的安全,从而让你的程序正常的运行!!
# 1.导入进程池/线程池模块
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import time
# 2.创建一个线程池对象,该对象括号内不传参数,默认是开设当前cpu个数*5的线程
pool = ThreadPoolExecutor(5) # 传入参数5,表示池子里固定创建了5个线程,这5个线程不会重复创建和销毁
def task(name):
print('%s来了'% name)
time.sleep(2)
# 3.朝池子中提交任务,第一个参数是函数名,第二个参数是函数需要传入的参数
"""
同步提交:提交任务之后原地等待返回结果,不往下执行任务
异步提交:提交任务之后不原地等待返回结果,继续往下执行
"""
# pool.submit(task,'zhang') # 注意:这里的提交是一个异步提交
# print('主')
# 优化
list = []
for i in range(20): # 向池子中提交20个任务。池子中只有5个线程
res = pool.submit(task,i) # 池方法异步提交之后有一个返回值,该返回值是一个future对象
# print(res.result()) # 该对象有一个result方法,可以用来返回对应线程函数的返回值,没有返回值则返回none
# result方法的使用使得submi异步提交变成了同步提交
list.append(res)
# 如果想等待所有的线程全部执行完毕,在往下执行代码,可以使用池的shutdown方法
pool.shutdown() # shutdown的作用是等待所有线程池运行完毕,再关闭所有线程池往下运行
for i in list:
print(i.result())
基本同线程池,不同的是以下部分:
# 1.导入进程池/线程池模块
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import time,os
pool = ProcessPoolExecutor(5) # 不传默认是cpu的个数
def task(name):
print('%s来了'% name)
time.sleep(2)
# call_back函数里面需要传一个参数,该参数就是res(一个future对象)
def call_back(n):
# 可以通过n.result()的方法获取task函数的返回值
print(n.result())
if __name__ == '__main__':
for i in range(20):
# add_done_callback方法是给submit这个异步提交添加一个回调机制,完成任务之后立刻回调结果,方法的参数是一个函数
res = pool.submit(task, i).add_done_callback(call_back)
协程其实就是一种在单线程下实现并发的操作,程序猿通过检测自己写的代码,一旦遇到了IO操作的代码,我们就编写代码进行切换,这样使得cpu一直处于运行状态,提高程序的运行效率!
gevent模块的引用时为了使得函数之间不断的切换+保存状态!!
"""
使用协程,就必须要我们通过代码实时检测程序是否进入到了IO操作,如果进入了IO操作,
就进行快速的切换,以此来实现并发的效果,提升程序的运行效率
"""
# 1.导入gevent模块的spawn模块,该模块是用来监测函数里面的IO操作的,但是spawn模块是无法监测一些常见的IO操作的
# 因此,需要导入gevent模块中的monkey模块,以此来监测所有的IO操作
from gevent import monkey,spawn
monkey.patch_all() # 猴子补丁
import time
def func1():
print('hhh')
time.sleep(2)
print('lalala')
def func2():
print('wwww')
time.sleep(3)
print('结束')
start_time = time.time()
g1 = spawn(func1) # spawn括号里是需要启动监测的函数名,函数名后面可以加需要传入的参数
g2 = spawn(func2) # 该方法是异步提交,有一个返回值,如果没有join方法会自动往下执行代码,结束程序
g2.join() # 等待函数执行完在往下执行
g1.join()
print(time.time()-start_time)
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------
我正在尝试使用ruby编写一个双线程客户端,一个线程从套接字读取数据并将其打印出来,另一个线程读取本地数据并将其发送到远程服务器。我发现的问题是Ruby似乎无法捕获线程内的错误,这是一个示例:#!/usr/bin/rubyThread.new{loop{$stdout.puts"hi"abc.putsefsleep1}}loop{sleep1}显然,如果我在线程外键入abc.putsef,代码将永远不会运行,因为Ruby将报告“undefinedvariableabc”。但是,如果它在一个线程内,则没有错误报告。我的问题是,如何让Ruby捕获这样的错误?或者至少,报告线程中的错误?
我是ruby的新手,我认为重新构建一个我用C#编写的简单聊天程序是个好主意。我正在使用Ruby2.0.0MRI(Matz的Ruby实现)。问题是我想在服务器运行时为简单的服务器命令提供I/O。这是从示例中获取的服务器。我添加了使用gets()获取输入的命令方法。我希望此方法在后台作为线程运行,但该线程正在阻塞另一个线程。require'socket'#Getsocketsfromstdlibserver=TCPServer.open(2000)#Sockettolistenonport2000defcommandsx=1whilex==1exitProgram=gets.chomp
我正在尝试使用以下代码通过将ffmpeg实用程序作为子进程运行并获取其输出并解析它来确定视频分辨率:IO.popen'ffmpeg-i'+path_to_filedo|ffmpegIO|#myparsegoeshereend...但是ffmpeg输出仍然连接到标准输出并且ffmepgIO.readlines是空的。ffmpeg实用程序是否需要一些特殊处理?或者还有其他方法可以获得ffmpeg输出吗?我在WinXP和FedoraLinux下测试了这段代码-结果是一样的。 最佳答案 要跟进mouviciel的评论,您需要使用类似pope
我目前正在用Ruby编写一个项目,它使用ActiveRecordgem进行数据库交互,我正在尝试使用ActiveRecord::Base.logger记录所有数据库事件具有以下代码的属性ActiveRecord::Base.logger=Logger.new(File.open('logs/database.log','a'))这适用于迁移等(出于某种原因似乎需要启用日志记录,因为它在禁用时会出现NilClass错误)但是当我尝试运行包含调用ActiveRecord对象的线程守护程序的项目时脚本失败并出现以下错误/System/Library/Frameworks/Ruby.frame
我有一个使用PDFKit呈现网页的pdf版本的Rails应用程序。我使用Thin作为开发服务器。问题是当我处于开发模式时。当我使用“bundleexecrailss”启动我的服务器并尝试呈现任何PDF时,整个过程会陷入僵局,因为当您呈现PDF时,会向服务器请求一些额外的资源,如图像和css,看起来只有一个线程.如何配置Rails开发服务器以运行多个工作线程?非常感谢。 最佳答案 我找到的最简单的解决方案是unicorn.geminstallunicorn创建一个unicorn.conf:worker_processes3然后使用它: