Peteryo01223 发表于 2021-6-8 15:57:57

Py: 加锁问题,我看不懂程序

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

问题:以下程序中,

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


# 线程安全
import threading
import time
number = 0
lock = threading.Lock()


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

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


time.sleep(3)
print('主线程结束, number = ' + str(number))

Twilight6 发表于 2021-6-8 19:29:24


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

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

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

# 线程安全
import threading
import time

number = 0
lock = threading.Lock()


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


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

print('主线程结束')

Peteryo01223 发表于 2021-6-9 09:30:44

本帖最后由 Peteryo01223 于 2021-6-9 09:34 编辑

Twilight6 发表于 2021-6-8 19:29
你 lk 是定义函数中的参数,当然可以随便命名的,开启线程时的 args 参数就是线程的传入参数,将 lock 这 ...

Traceback (most recent call last):
File "C:/Users/user/AppData/Local/Programs/Python/Python38/202101125a.py", line 20, in <module>
    start_time = time.clock()
AttributeError: module 'time' has no attribute 'clock'
>>>
问题:
1. 你的代码,我试了一下,报错了,如上。是不是有个变量名,没改?
2. 感谢你耐心的简介。你说:lk 是定义函数中的参数,当然可以随便命名的,开启线程时的 args 参数就是线程的传入参数,将 lock 这个锁已经传递给 lk 了。我还是没看懂。
t = threading.Thread(target=add, args=(lock,))
上面这一句,跟 lk 有什么关系呢?

Twilight6 发表于 2021-6-9 09:33:22

Peteryo01223 发表于 2021-6-9 09:30
你的代码,我试了一下,报错了。是不是有个变量名,没改?



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

Peteryo01223 发表于 2021-6-9 09:49:56

Twilight6 发表于 2021-6-9 09:33
Python 3.8 以上 time.clock 改成了 time.perf_counter ,你改下即可

成功了。
# 线程安全
import threading
import time

number = 0
lock = threading.Lock()


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


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

print('主线程结束')
run后结果:
开始进程1
开始进程2
主线程结束
>>> 子线程 1.9267 总执行时间
子线程 3.9983 总执行时间

Peteryo01223 发表于 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 之间的联系。

Twilight6 发表于 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 的别名

Peteryo01223 发表于 2021-6-9 10:15:40

Twilight6 发表于 2021-6-9 09:56
这里 for 循环的 print 我打错了,不是进程是线程




好的 再次感谢您

Twilight6 发表于 2021-6-9 10:28:40

Peteryo01223 发表于 2021-6-9 10:15
好的 再次感谢您

没事没事
页: [1]
查看完整版本: Py: 加锁问题,我看不懂程序