zoukankan      html  css  js  c++  java
  • 互斥锁与多线程间共享全局变量

    互斥锁

    一、 代码展示

    ① 没加锁(X)

    import threading
    
    num = 0
    
    
    def write1():
    
        global num
        i = 1
        while i <= 1000000:
            num += 1
            i += 1
    
        print("result1:%d" % num)
    
    
    def write2():
    
        global num
        i = 1
        while i <= 1000000:
            # 由于 num 是全局变量,但num += 1 是分三步执行的(详情看总结)
            # 若没有加锁,就会出现抢夺资源( num +=1 还没执行完,另一个线程拿这个变量去使用),就会导致 num 的最终值出现错误
            num += 1
            i += 1
    
        print("result2:%d" % num)
    
    
    def main():
    
        # 创建两个线程
    
        p1 = threading.Thread(target=write1)
        p2 = threading.Thread(target=write2)
    
        # 开启线程
        p1.start()
        p2.start()
    
    
    if __name__ == "__main__":
        main()
    
    

    运行结果

    result1:1180321
    result2:1567595
    

    以上 result2 结果不是一个定值,各种值情况都会出现

    ② 加了锁(√)

    import threading
    
    num = 0
    
    
    def write1(lock):
    
        global num
        i = 1
        while i <= 1000000:
            # 此处加了锁
            lock.acquire()
            num += 1
            lock.release()
            i += 1
    
        print("result1:%d" % num)
    
    
    def write2(lock):
    
        global num
        i = 1
        while i <= 1000000:
            
            # 此处加了锁,跑得快的线程会先上锁,使得另一个线程遇到锁时会堵塞,即原地等待。
            lock.acquire()
    
            # 由于 num 是全局变量,但num += 1 是分三步执行的
            num += 1
            
            # 运行到此处将进行解锁,解除另一个线程的堵塞状态。随后另一个线程上锁,
            # 该线程则堵塞,保证了不会出现资源竞争的情况
            lock.release()
            i += 1
    
        print("result2:%d" % num)
    
    
    def main():
    
        # 创建一个锁
        lock = threading.Lock()
    
        # 创建两个线程
    
        p1 = threading.Thread(target=write1, args=(lock,))
        p2 = threading.Thread(target=write2, args=(lock,))
    
        # 开启线程
        p1.start()
        p2.start()
    
    
    if __name__ == "__main__":
        main()
    
    

    运行结果

    result1:1996142
    result2:2000000  # 因为每个线程都会1000000次+1,所以哪个线程最后一次+1输出结果肯定是2000000
    

    二、 总结

    • ① 线程之间是共用全局变量的,因为线程是一个进程里分出来的几个任务,使用的是用同一份代码,同样的变量与资源

    • ② 互斥锁一般用在线程需要 共享全局变量 的时候

    • 进程与线程之间的关系与区别:

      • ① 进程 包含 多个线程
      • ② 进程间 不共用 变量与资源;线程间 共用 变量与资源
    • ④ num += 1 分三步执行:

        1. cpu从内存中读取num的值(例如 num = 0
        2. cpu把读取到的num值加1(num + 1 = 1
        3. cpu把计算完的值重新赋值给内存(num = 1
  • 相关阅读:
    XAML语言
    Sqlite 数据库插入标示字段 获取新Id 及利用索引优化查询
    提高C#编程水平的50个要点 ——学生的迷茫
    734条高频词组笔记
    C#读取ini配置文件
    MD5加密
    SQL Server 2000 及 2005 端口修改
    Java控制台程序20例
    Tomcat 6.0+ SQL Server 2005连接池的配
    阿里巴巴离职DBA 35岁总结的职业生涯
  • 原文地址:https://www.cnblogs.com/fry-hell/p/12825897.html
Copyright © 2011-2022 走看看