异常飞出去,锁还在不在

👁️ 3 人浏览 💬 0 人评论 ❤️ 添加收藏

(每道题开头都有同一段:上面那几样。)

贯穿全条的几样东西:

Counter / SafeCounter   读-睡-写的计数器;Safe 版用 with self.lock 包住三步(conc_03 的写法)
hammer(counter, workers, times)   开几条线程各加 times 次,交回最终的 n(真线程,题里只比大小)
probe(lock)   这把锁现在能不能立刻拿到(acquire(blocking=False),拿到就放回)——用它「看」锁的状态,不卡住
Guard(lock)   手写的 with 替身:__enter__ 拿、__exit__ 放

两种写法各让临界区里抛一次异常,看异常之后锁是不是放开了:

import threading
import time


class Counter:
    def __init__(self):
        self.n = 0

    def inc(self):
        tmp = self.n
        time.sleep(0.001)
        self.n = tmp + 1


class SafeCounter(Counter):
    def __init__(self):
        super().__init__()
        self.lock = threading.Lock()

    def inc(self):
        with self.lock:
            tmp = self.n
            time.sleep(0.001)
            self.n = tmp + 1


def hammer(counter, workers=2, times=30):
    def job():
        for _ in range(times):
            counter.inc()
    ts = [threading.Thread(target=job) for _ in range(workers)]
    for t in ts:
        t.start()
    for t in ts:
        t.join()
    return counter.n


def probe(lock):
    """这把锁现在能不能立刻拿到?能就拿了再放回去,交回 True;拿不到交回 False。"""
    if lock.acquire(blocking=False):
        lock.release()
        return True
    return False


class Guard:
    """手写的 with 替身:进就 acquire,出就 release——不管是正常出还是异常出。"""
    def __init__(self, lock):
        self.lock = lock

    def __enter__(self):
        self.lock.acquire()
        return self

    def __exit__(self, exc_type, exc, tb):
        self.lock.release()
        return False


def by_with(lock):
    with lock:
        raise ValueError("坏了")


def by_hand(lock):
    lock.acquire()
    raise ValueError("坏了")
    lock.release()


res = []
for fn in (by_with, by_hand):
    L = threading.Lock()
    try:
        fn(L)
    except ValueError:
        pass
    res.append(str(probe(L)))
print("/".join(res))
提交你的答案
请登录后提交答案。
去登录
代码编辑器
Ctrl + Enter 运行
本次输入:
输出:

                        
👩‍🏫
AI
💬 题目评论

全部评论