簡體   English   中英

time.sleep 與 threading.Lock 的交互

[英]interaction of time.sleep with threading.Lock

我試圖了解 Python 中的鎖並編寫了以下示例代碼。

import threading
import time

LOCK = threading.Lock()

class Printer(threading.Thread):
    def __init__(self, *args, **kwargs):
        super(Printer, self).__init__(*args, **kwargs)
        self.daemon = True
        self.i = 0

    def run(self):
        while True:
            with LOCK:
                print(self.i)
                self.i += 1
            time.sleep(1)

raw_input('press enter to start thread\n')
Printer().start()
raw_input('press enter to pause thread\n')
LOCK.acquire()
raw_input('press enter to resume thread\n')
LOCK.release()
raw_input('press enter to exit program\n')
print('bye!')

這按預期工作並產生 output ,例如:

press enter to start thread

0
 press enter to pause thread
1
2
3
4

press enter to resume thread

press enter to exit program
5
6
7
8

bye!

問題

為什么在with塊中縮進time.sleep(1)會破壞程序?

def run(self):
    while True:
        with LOCK:
            print(self.i)
            self.i += 1
            time.sleep(1)

打印機不能中斷!

將您的代碼更改為此,看看發生了什么:

import threading
import time

LOCK = threading.Lock()


class Printer(threading.Thread):
    def __init__(self, *args, **kwargs):
        super(Printer, self).__init__(*args, **kwargs)
        self.daemon = True
        self.i = 0

    def run(self):
        while True:
            with LOCK:
                print(self.i)
                self.i += 1
                time.sleep(1)


raw_input('press enter to start thread\n')
Printer().start()
raw_input('press enter to pause thread\n')
print('acquiring...')
LOCK.acquire()
print('acquired')
raw_input('press enter to resume thread\n')
LOCK.release()
raw_input('press enter to exit program\n')
print('bye!')

當您的代碼嘗試運行LOCK.acquire()時,我認為比賽從with LOCKLOCK.acquire()開始,並且線程大部分時間都贏得了游戲並獲得 LOCK 1 秒。 但是在第一種方法中,當 Printer() 等待 1 秒時,主線程獲取 LOCK 沒有任何問題,因為它是空閑的。 我希望你能明白。 對不起我的語言:))

Hameda169想通了!

我編寫了一個帶有“on”和“off”按鈕的小型演示 GUI,以便將來解釋/記住這個概念。

如果您在 LOCK.release() 之后LOCK.release() time.sleep(0.01) ,則 GUI 按鈕在嘗試獲取鎖時可能會凍結很長時間。

它還展示了為什么需要鎖。 如果你在onoff回調with LOCK注釋掉,你很快就會在按下按鈕時得到一個AttributeError

# see what happens when there's no sleep AFTER release
# see what happens if on and off functions do not acquire the lock

import Tkinter as tk
import threading
import time
import ttk

class ON(object):
    pass

class Printer(threading.Thread):
    def __init__(self, *args, **kwargs):
        super(Printer, self).__init__()
        self.daemon = True
        self.on = None
        self.i = 0

    def run(self):
        while True:
            LOCK.acquire()
            if self.on is not None: 
                time.sleep(0.1) # make it very likely that self.on can be set to
                                # None from outside before trying to access
                                # dummy_attribute -> AttributeError w/o lock!
                self.on.dummy_attribute # can error without lock
                print(self.i)
                self.i += 1
            LOCK.release()

            time.sleep(0.01) # must sleep after release, else lock can be
                             # acquired immediately again!

ROOT = tk.Tk()
PRINTER = Printer()
LOCK = threading.Lock()

def on():
    with LOCK:
        PRINTER.on = ON()
        PRINTER.on.dummy_attribute = 'foo'

def off():
    with LOCK:
        PRINTER.on = None

ttk.Button(ROOT, text='on', command=on).grid()
ttk.Button(ROOT, text='off', command=off).grid()

if __name__ == '__main__':
    PRINTER.start()
    ROOT.mainloop()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM