鱼C论坛

 找回密码
 立即注册
查看: 3667|回复: 8

[已解决]Py: 加锁问题,我看不懂程序

[复制链接]
发表于 2021-6-8 15:57:57 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 Peteryo01223 于 2021-6-8 16:00 编辑

问题:以下程序中,
  • lk 是我自己命名的,请问,lk 它是一个变量吗?
  • lk 是如何与 lock 配合,成功加锁的呢?我怎么看不到它俩在程序中的联系呀?
  • with lk,如果换成写 with each,也能成功加锁,是吗?


  1. # 线程安全
  2. import threading
  3. import time
  4. number = 0
  5. lock = threading.Lock()


  6. def add(lk):
  7.     global number
  8.     # 加锁
  9.     with lk:
  10.         for _ in range(1000000):
  11.             number += 1
  12.         print('子线程 %s 执行结束后:number = %d' % (threading.current_thread().getName(), number))
  13.         # 解锁
  14.         

  15. for i in range(2):
  16.     t = threading.Thread(target=add, args = (lock,))
  17.     t.start()


  18. time.sleep(3)
  19. print('主线程结束, number = ' + str(number))
复制代码
最佳答案
2021-6-9 09:33:22
Peteryo01223 发表于 2021-6-9 09:30
你的代码,我试了一下,报错了。是不是有个变量名,没改?



Python 3.8 以上 time.clock 改成了 time.perf_counter ,你改下即可

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-6-8 19:29:24 | 显示全部楼层

你 lk 是定义函数中的参数,当然可以随便命名的,开启线程时的 args 参数就是线程的传入参数,将 lock 这个锁已经传递给 lk 了

如果你换成 each ,那么如果 each 也是你创建的一个锁,当然可以,若不是锁就不行,另外代码改成这样好看出来些

你会发现线程一起开始且停下的时间也都为 2s 但是先加锁的先执行完毕,后加锁的后执行

  1. # 线程安全
  2. import threading
  3. import time

  4. number = 0
  5. lock = threading.Lock()


  6. def add(lk):
  7.     global number
  8.     # 加锁
  9.     with lk:
  10.         time.sleep(2)
  11.         thread_time = time.clock()
  12.         print('子线程 %.4f 总执行时间' % (thread_time - start_time))
  13.         # 解锁


  14. for i in range(2):
  15.     start_time = time.clock()
  16.     t = threading.Thread(target=add, args=(lock,))
  17.     t.start()
  18.     print(f'开始进程{i+1}')

  19. print('主线程结束')
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-9 09:30:44 | 显示全部楼层
本帖最后由 Peteryo01223 于 2021-6-9 09:34 编辑
Twilight6 发表于 2021-6-8 19:29
你 lk 是定义函数中的参数,当然可以随便命名的,开启线程时的 args 参数就是线程的传入参数,将 lock 这 ...

  1. Traceback (most recent call last):
  2.   File "C:/Users/user/AppData/Local/Programs/Python/Python38/202101125a.py", line 20, in <module>
  3.     start_time = time.clock()
  4. AttributeError: module 'time' has no attribute 'clock'
  5. >>>
复制代码

问题:
1. 你的代码,我试了一下,报错了,如上。是不是有个变量名,没改?
2. 感谢你耐心的简介。你说:lk 是定义函数中的参数,当然可以随便命名的,开启线程时的 args 参数就是线程的传入参数,将 lock 这个锁已经传递给 lk 了。我还是没看懂。
  1. t = threading.Thread(target=add, args=(lock,))
复制代码

上面这一句,跟 lk 有什么关系呢?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-6-9 09:33:22 | 显示全部楼层    本楼为最佳答案   
Peteryo01223 发表于 2021-6-9 09:30
你的代码,我试了一下,报错了。是不是有个变量名,没改?



Python 3.8 以上 time.clock 改成了 time.perf_counter ,你改下即可

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-9 09:49:56 | 显示全部楼层
Twilight6 发表于 2021-6-9 09:33
Python 3.8 以上 time.clock 改成了 time.perf_counter ,你改下即可

成功了。
  1. # 线程安全
  2. import threading
  3. import time

  4. number = 0
  5. lock = threading.Lock()


  6. def add(lk):
  7.     global number
  8.     # 加锁
  9.     with lk:
  10.         time.sleep(2)
  11.         thread_time = time.perf_counter()
  12.         print('子线程 %.4f 总执行时间' % (thread_time - start_time))
  13.         # 解锁


  14. for i in range(2):
  15.     start_time = time.perf_counter()
  16.     t = threading.Thread(target=add, args=(lock,))
  17.     t.start()
  18.     print(f'开始进程{i+1}')

  19. print('主线程结束')
复制代码

run后结果:
  1. 开始进程1
  2. 开始进程2
  3. 主线程结束
  4. >>> 子线程 1.9267 总执行时间
  5. 子线程 3.9983 总执行时间
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-9 09:53:31 | 显示全部楼层
Twilight6 发表于 2021-6-9 09:33
Python 3.8 以上 time.clock 改成了 time.perf_counter ,你改下即可

lk 和 with lk,我还是没明白,能帮我再进一步,解释一下么?他们是怎么起到 lock 的作用的?看不出 lk 和 lock 之间的联系。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-6-9 09:56:20 | 显示全部楼层
Peteryo01223 发表于 2021-6-9 09:53
lk 和 with lk,我还是没明白,能帮我再进一步,解释一下么?他们是怎么起到 lock 的作用的?看不出 lk  ...




这里 for 循环的 print 我打错了,不是进程是线程

def add(lk):
     ......

t = threading.Thread(target=add, args=(lock,))


就是 add 函数往其中传入了 lock 变量,lock 不就赋值到 lk 上了吗

相当于 lk 是 lock 的别名
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-9 10:15:40 | 显示全部楼层
Twilight6 发表于 2021-6-9 09:56
这里 for 循环的 print 我打错了,不是进程是线程

好的 再次感谢您
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-6-9 10:28:40 | 显示全部楼层

没事没事
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-25 13:06

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表