线程-锁

线程-锁


  1"""
  2Author: wangy325
  3Date: 2024-08-07 19:38:19
  4Description: 锁
  5"""
  6from threading import Thread, Lock, current_thread
  7
  8"""
  9python中没有类似Java synchronised同步关键字, 使用锁与条件来实现同步。
 10"""
 11
 12# ############### #
 13#       锁        #
 14# ############### #
 15
 16shared_int = 0
 17lock = Lock()
 18
 19
 20def incr_n_times(n):
 21    """
 22    挺离谱的, 明明可以看到线程竞争都乱成一锅粥了
 23    最后的结果竟然是正确的 :-)
 24    """
 25    global shared_int
 26    print(f"{current_thread().name}: >>>>{shared_int}")
 27    for i in range(n):
 28        shared_int += 1
 29    print(f"{current_thread().name}: <<<<{shared_int}")
 30
 31
 32def safe_incr_n_times(n):
 33    global shared_int
 34    lock.acquire()
 35    print(f"{current_thread().name}: >>>>{shared_int}")
 36    for i in range(n):
 37        shared_int += 1
 38    print(f"{current_thread().name}: <<<<{shared_int}")
 39    lock.release()
 40
 41
 42def incr_with_x_threads(x, func, n):
 43    # 列表推导式
 44    threads = [Thread(target=func, args=(n,)) for i in range(x)]
 45    start = time.time()
 46    global shared_int
 47    shared_int = 0
 48    for t in threads:
 49        t.start()
 50    for t in threads:
 51        t.join()
 52    print(f"finished in {time.time() - start}\n"
 53          f"shared expected: {n * x}\n"
 54          f"shared actual: {shared_int}\n"
 55          f"difference: {n * x - shared_int}({100 - shared_int / n / x * 100}%)")
 56
 57
 58# ##############################  #
 59#   这个栗子更好证明线程对资源的争夺    #
 60# ##############################  #
 61balance = 100
 62
 63
 64def withdraw_unsafe(money):
 65    """
 66    很明显可以看到2个线程同时进来, 同时获得最大余额
 67    :param money:
 68    :return:
 69    """
 70    global balance
 71    if balance >= money:
 72        time.sleep(1)
 73        balance -= money
 74        print(f"{current_thread().name}: withdraw {money}")
 75    else:
 76        print(f"{current_thread().name}: balance ({balance} < {money}) not enough")
 77
 78
 79def withdraw_safe(money):
 80    global balance
 81    lock.acquire()
 82    if balance >= money:
 83        balance -= money
 84        print(f"{current_thread().name}: withdraw {money}")
 85    else:
 86        print(f"{current_thread().name}: balance ({balance} < {money}) not enough")
 87    lock.release()
 88
 89
 90def withdraw_multi_t(func, m):
 91    threads = [Thread(target=func, args=(m,)) for i in range(2)]
 92    for t in threads:
 93        t.start()
 94    for t in threads:
 95        t.join()
 96    print(f"balance: {balance}")
 97
 98
 99if __name__ == '__main__':
100    # incr_with_x_threads(10, incr_n_times, 1000000)
101    # incr_with_x_threads(10, safe_incr_n_times, 1000000)
102    withdraw_multi_t(withdraw_unsafe, 80)
103    # withdraw_multi_t(withdraw_safe, 80)