zoukankan      html  css  js  c++  java
  • python__系统 : 线程

    线程之间,全局变量可以共享,但是局部变量依然是不共享的,线程的创建方式: threading.Thread(),还可以定义一个类继承Thread,重写他的run方法,具体和进程的写法一样.

    那么,线程之前全局变量共享,如果两个线程同时修改一个全局变量,就会有一些麻烦,所以需要用到互斥锁:

    from threading import Thread, Lock
    import time
    
    g_num = 0
    
    def test1():
        global g_num
        mutex.acquire()           <------------------------------
        for i in range(1000000):
            g_num += 1
        mutex.release()          <-----------------------------
        print(g_num)
    
    def test2():
        global g_num
        mutex.acquire()       <----------------------
        for i in range(1000000):
            g_num += 1
        mutex.release()       <------------------------
        print(g_num)
    
    mutex = Lock()
    
    t1 = Thread(target=test1)
    t1.start()
    
    t2 = Thread(target=test2)
    t2.start()
    
    >>>185734 1
       1000000
       2000000

    Lock() 是创建一把锁,用acquire() 的方式加锁 , release() 的方式解锁.  如果一个线程对一个变量加锁,剩下的线程就只能在等待,解锁之后用通知(还有一种耗费资源的方式是轮询) 的方式给等待的线程传递信息,锁已经解开.

    需要注意应该避免死锁, Lock 的 acquire() 里面有两个参数 blocking=True 默认是True 如果已经上锁,那么就一直在这等,等到锁解开为止,也就是堵塞. 改成False 的话如果已上锁那么就跳过这个加锁操作,所以一般搭配 if 使用 加锁成功返回值True. 还有一个参数timeout=-1 ,默认-1.就是延迟,如果改成正数,那么就会在等待多少秒之后才放弃加锁.

    同步 : 协同步调,按预定的先后次序运行. 异步:不确定什么时候运行.

    threading.local() 创建一个对象,里面可以保存一些类似字典一样的参数,如 localVal = threading.local()

    localVal.val = name这条语句可以储存一个变量到当前线程,如果在另外一个线程里面再次对localVal.val进行赋值,

    那么会在另外一个线程单独创建内存空间来存储,也就是说在不同的线程里面赋值 不会覆盖之前的值,因为每个

    线程里面都有一个单独的空间来保存这个数据,而且这个数据是隔离的,其他线程无法访问,就像这张图一样:

    最后,生产者与消费者模型:

    from queue import Queue
    import time, threading
    
    class Producer(threading.Thread):
        def run(self):
            global queue
            count = 0
            while True:
                if queue.qsize() < 1000:
                    for i in range(100):
                        count = count + 1
                        msg = '生成产品' + str(count)
                        queue.put(msg)
                        print(msg)
                time.sleep(0.5)
    
    class Consumer(threading.Thread):
        def run(self):
            global queue
            while True:
                if queue.qsize() > 100:
                    for i in range(3):
                        msg = self.name + '消费了' + queue.get()
                        print(msg)
                time.sleep(0.5)
    
    
    if __name__ == '__main__':
        queue = Queue()
    
        for i in range(500):
            queue.put('初始产品' + str(i))
        for i in range(2):
            p = Producer()
            p.start()
        for i in range(5):
            c = Consumer()
            c.start()

    from queue import Queue (python2 是 from Queue) 这是队列,先进先出,用来缓冲数据, 有 get put qsize 等方法,和进程的那个进程间通信的队列(from multiprocessing import Queue) 基本一样.

    思路理解即可.

  • 相关阅读:
    笔记:Linux进程间通信机制
    Linux下C/C++和lua交互-Table
    @JsonFormat时间格式化注解使用
    关于 mybatis 报invalid comparison: java.util.Arrays$ArrayList and java.lang.String异常
    @RestControllerAdvice作用及原理
    MySQL 中 datetime 和 timestamp 的区别与选择
    idea提交svn忽略.class等文件的相关配置(so easy)
    PLSQL Developer建表时注释(COMMENT)中文乱码的解决方案(Windows)
    oracle客户端安装与配置
    PLSQL安装、PLSQL汉化、激活
  • 原文地址:https://www.cnblogs.com/cccy0/p/9085992.html
Copyright © 2011-2022 走看看