精华内容
下载资源
问答
  • 2020-11-29 02:32:16

    下面这段代码在 windows 下运行就报错 NameError: name 'SEM' is not defined

    在 windows7 windows10 测试 报错

    在 Mac Linux 下测试 能正常运行

    如果我在代码的最上面给 SEM 和 TIME_OUT 赋值后,就能正常运行

    但是我需要用户加参数将值带进去,而不是事先定义好,所以只能放到 argparse 里面。我现在很疑惑,这个问题能解决吗?

    时间过了两天了,依旧没有解决这个问题,希望小伙伴们能和我一起讨论一下怎么回事,谢谢!

    # /usr/bin/env python

    # _*_ coding:utf-8 _*_

    import argparse, datetime, time

    import threading

    from multiprocessing import Pool

    def test(i):

    with SEM:

    print(i)

    time.sleep(TIME_OUT)

    def test1(c):

    threads = []

    for i in range(int(200)):

    t = threading.Thread(target=test, args=(i,))

    t.start()

    threads.append(t)

    for t in threads:

    t.join()

    def main():

    start_time = time.time()

    print(datetime.datetime.now().strftime('Start Time: %m/%d/%Y %H:%M:%S'))

    p = Pool(int(args.PROCESS))

    for i in range(10):

    p.apply_async(test1, args=(i,))

    p.close()

    p.join()

    print(datetime.datetime.now().strftime('Complete time: %m/%d/%Y %H:%M:%S'))

    print("Total time:%s" % (time.time() - start_time))

    if __name__ == '__main__':

    parser = argparse.ArgumentParser(description='test')

    parser.add_argument('-m', dest='PROCESS', type=int, help='多进程数量,默认 5', default=5)

    parser.add_argument('-t', dest='THREAD', type=int, help='多线程数量,默认 20', default=20)

    parser.add_argument('-o', dest='OVERTIME', type=int, help='超时时间 默认 2', default=2)

    args = parser.parse_args()

    SEM = threading.Semaphore(int(args.THREAD))

    TIME_OUT = int(args.OVERTIME)

    main()

    更多相关内容
  • 一,并发与并行并发:CPU使用一个核心在各程序...可以真正的提升执行速度二,遗留问题Python多线程只能使用一个核心,解释器的设计遗留问题利用CPU多核只能通过多进程,或者在线程中使用C语言扩展三,使用ThreadLoca...

    一,并发与并行

    并发:CPU使用一个核心在各程序之间交替执行,形成一种让人以为程序同时运行的错觉,并不会真正的提升执行效率和速度

    并行:CPU使用多个核心同时执行多个程序,各程序指令运行在不同的CPU内核上面,程序平行的向前推进,可以真正的提升执行速度

    二,遗留问题

    Python多线程只能使用一个核心,解释器的设计遗留问题

    利用CPU多核只能通过多进程,或者在线程中使用C语言扩展

    三,使用ThreadLocal来读写全局变量

    多线程共享全局变量,非常容易把全局变量改乱,所以在全局变量声明ThreadLocal对象实例(可以理解为一个dict),在其对象上绑定的所有属性数据,在每个线程中都是独立的,不同的

    ThreadLocal最常用的地方就是为每个线程绑定一个数据库连接,HTTP请求,用户身份信息等

    四,线程对比进程

    多进程和多线程,这是实现多任务最常用的两种方式。现在,我们来讨论一下这两种方式的优缺点。

    首先,要实现多任务,通常我们会设计Master-Worker模式,Master负责分配任务,Worker负责执行任务,因此,多任务环境下,通常是一个Master,多个Worker。

    如果用多进程实现Master-Worker,主进程就是Master,其他进程就是Worker。

    如果用多线程实现Master-Worker,主线程就是Master,其他线程就是Worker。

    多进程模式最大的优点就是稳定性高,因为一个子进程崩溃了,不会影响主进程和其他子进程。(当然主进程挂了所有进程就全挂了,但是Master进程只负责分配任务,挂掉的概率低)著名的Apache最早就是采用多进程模式。

    多进程模式的缺点是创建进程的代价大,在Unix/Linux系统下,用fork调用还行,在Windows下创建进程开销巨大。另外,操作系统能同时运行的进程数也是有限的,在内存和CPU的限制下,如果有几千个进程同时运行,操作系统连调度都会成问题。

    多线程模式通常比多进程快一点,但是也快不到哪去,而且,多线程模式致命的缺点就是任何一个线程挂掉都可能直接造成整个进程崩溃,因为所有线程共享进程的内存。在Windows上,如果一个线程执行的代码出了问题,你经常可以看到这样的提示:“该程序执行了非法操作,即将关闭”,其实往往是某个线程出了问题,但是操作系统会强制结束整个进程。

    在Windows下,多线程的效率比多进程要高,所以微软的IIS服务器默认采用多线程模式。由于多线程存在稳定性的问题,IIS的稳定性就不如Apache。为了缓解这个问题,IIS和Apache现在又有多进程+多线程的混合模式,真是把问题越搞越复杂。

    线程切换

    无论是多进程还是多线程,只要数量一多,效率肯定上不去,为什么呢?

    我们打个比方,假设你不幸正在准备中考,每天晚上需要做语文、数学、英语、物理、化学这5科的作业,每项作业耗时1小时。

    如果你先花1小时做语文作业,做完了,再花1小时做数学作业,这样,依次全部做完,一共花5小时,这种方式称为单任务模型,或者批处理任务模型。

    假设你打算切换到多任务模型,可以先做1分钟语文,再切换到数学作业,做1分钟,再切换到英语,以此类推,只要切换速度足够快,这种方式就和单核CPU执行多任务是一样的了,以幼儿园小朋友的眼光来看,你就正在同时写5科作业。

    但是,切换作业是有代价的,比如从语文切到数学,要先收拾桌子上的语文书本、钢笔(这叫保存现场),然后,打开数学课本、找出圆规直尺(这叫准备新环境),才能开始做数学作业。操作系统在切换进程或者线程时也是一样的,它需要先保存当前执行的现场环境(CPU寄存器状态、内存页等),然后,把新任务的执行环境准备好(恢复上次的寄存器状态,切换内存页等),才能开始执行。这个切换过程虽然很快,但是也需要耗费时间。如果有几千个任务同时进行,操作系统可能就主要忙着切换任务,根本没有多少时间去执行任务了,这种情况最常见的就是硬盘狂响,点窗口无反应,系统处于假死状态。

    所以,多任务一旦多到一个限度,就会消耗掉系统所有的资源,结果效率急剧下降,所有任务都做不好。

    计算密集型 vs. IO密集型

    是否采用多任务的第二个考虑是任务的类型。我们可以把任务分为计算密集型和IO密集型。

    计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如计算圆周率、对视频进行高清解码等等,全靠CPU的运算能力。这种计算密集型任务虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低,所以,要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数。

    计算密集型任务由于主要消耗CPU资源,因此,代码运行效率至关重要。Python这样的脚本语言运行效率很低,完全不适合计算密集型任务。对于计算密集型任务,最好用C语言编写。

    第二种任务的类型是IO密集型,涉及到网络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)。对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。常见的大部分任务都是IO密集型任务,比如Web应用。

    IO密集型任务执行期间,99%的时间都花在IO上,花在CPU上的时间很少,因此,用运行速度极快的C语言替换用Python这样运行速度极低的脚本语言,完全无法提升运行效率。对于IO密集型任务,最合适的语言就是开发效率最高(代码量最少)的语言,脚本语言是首选,C语言最差。

    异步IO

    考虑到CPU和IO之间巨大的速度差异,一个任务在执行的过程中大部分时间都在等待IO操作,单进程单线程模型会导致别的任务无法并行执行,因此,我们才需要多进程模型或者多线程模型来支持多任务并发执行。

    现代操作系统对IO操作已经做了巨大的改进,最大的特点就是支持异步IO。如果充分利用操作系统提供的异步IO支持,就可以用单进程单线程模型来执行多任务,这种全新的模型称为事件驱动模型,Nginx就是支持异步IO的Web服务器,它在单核CPU上采用单进程模型就可以高效地支持多任务。在多核CPU上,可以运行多个进程(数量与CPU核心数相同),充分利用多核CPU。由于系统总的进程数量十分有限,因此操作系统调度非常高效。用异步IO编程模型来实现多任务是一个主要的趋势。

    对应到Python语言,单线程的异步编程模型称为协程,有了协程的支持,就可以基于事件驱动编写高效的多任务程序。我们会在后面讨论如何编写协程。

    五,可以使用multiprocessing.managers实现分布式进程共享通信处理内容

    展开全文
  • 一句话总结:父进程创建子进程时,子进程会复制父进程的内存(包括锁状态),需仔细处理。 1、死锁例子 #include #include #include #include pthread_mutex_t mutex = PTHREAD_MUTEX_...

    一句话总结:父进程创建子进程时,子进程会复制父进程的内存(包括锁状态),需仔细处理。

    1、死锁例子

    #include <stdio.h>

    #include <time.h>

    #include <pthread.h>

    #include <unistd.h>


    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;


    void* doit(void* arg)

    {

    printf("pid = %d begin doit ...\n",static_cast<int>(getpid()));

    pthread_mutex_lock(&mutex);

    struct timespec ts = {2, 0};

    nanosleep(&ts, NULL);

    pthread_mutex_unlock(&mutex);

    printf("pid = %d end doit ...\n",static_cast<int>(getpid()));


    return NULL;

    }


    int main(void)

    {

    printf("pid = %d Entering main ...\n", static_cast<int>(getpid()));

    pthread_t tid;

    pthread_create(&tid, NULL, doit, NULL);

    struct timespec ts = {1, 0};

    nanosleep(&ts, NULL);

    if (fork() == 0)

    {

    doit(NULL);

    }

    pthread_join(tid, NULL);

    printf("pid = %d Exiting main ...\n",static_cast<int>(getpid()));


    return 0;

    }


    运行结果:


    通过查询进程可以发现死锁了,子进程3071无法往下执行。

    原因:父进程创建的线程调用doit()后,对mutex加了锁;此时fork了一个子进程,子进程复制父进程的内存,包括此时的mutex锁状态;父进程接着往后执行直到结束,而子进程调用了doit(),此时mutex处于加锁状态,一直等待,造成死锁。


    2、解决死锁

    如何解决上述问题呢,我们需要在fork子进程前将锁释放掉,fork之后再将父进程的锁加上。用

    int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));
    pthread_atfork()在fork()之前调用,当调用fork时,内部创建子进程前在父进程中会调用prepare,内部创建子进程成功后,父进程会调用parent ,子进程会调用child。

    不过还是尽量少将多进程多线程混在一起。


    #include <stdio.h>

    #include <time.h>

    #include <pthread.h>

    #include <unistd.h>


    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;


    void* doit(void* arg)

    {

    printf("pid = %d begin doit ...\n",static_cast<int>(getpid()));

    pthread_mutex_lock(&mutex);

    struct timespec ts = {2, 0};

    nanosleep(&ts, NULL);

    pthread_mutex_unlock(&mutex);

    printf("pid = %d end doit ...\n",static_cast<int>(getpid()));


    return NULL;

    }


    void prepare(void)

    {

        printf("pid = %d prepare ...\n", static_cast<int>(getpid()));

        pthread_mutex_unlock(&mutex);

    }


    void parent(void)

    {

        printf("pid = %d parent ...\n", static_cast<int>(getpid()));

        pthread_mutex_lock(&mutex);

    }


    void child(void)

    {

        printf("pid = %d child ...\n", static_cast<int>(getpid()));

    }


    int main(void)

    {

    pthread_atfork(prepare, parent, child);

    printf("pid = %d Entering main ...\n", static_cast<int>(getpid()));

    pthread_t tid;

    pthread_create(&tid, NULL, doit, NULL);

    struct timespec ts = {1, 0};

    nanosleep(&ts, NULL);

    if (fork() == 0)

    {

        doit(NULL);

    }

    pthread_join(tid, NULL);

    printf("pid = %d Exiting main ...\n",static_cast<int>(getpid()));


    return 0;

    }


    结果:






    展开全文
  • 进程线程的概念:进程是资源占用的最小单位线程是内核调度执行的最小单位进程线程的主要区别:进程之间是彼此独立的,由master进程通过fork()系统调用派生子进程线程是共享内存空间的,主线程派生子线程why?...

    what?

    进程和线程的概念:

    进程是资源占用的最小单位

    线程是内核调度执行的最小单位

    进程和线程的主要区别:

    进程之间是彼此独立的,由master进程通过fork()系统调用派生子进程

    线程是共享内存空间的,主线程派生子线程

    why?

    进程和线程的优缺点:

    进程:

    优点:进程由于各自有独立的内存空间,所以更加稳定,子进程之间不受影响,但是主进程崩溃会导致全局,而且在python中不受GIL(全局解释器锁)限制,可以充分利用多核cpu

    缺点:对于内存资源占用比较高,而且创建一个进程的代价比线程要大

    线程:

    优点:由于共享内存空间,所以资源占用比较小,并且创建的代价小于进程,在python中受到GIL的限制,导致只能使用一个cpu核心,所以某一时刻运行的线程只有一个

    缺点:由于共享内存空间也导致了缺点,资源征用的问题(python中可以通过锁的机制限制),并且一个线程的崩溃可能导致整个进程崩溃

    fork()系统调用:

    是unix/linux上比较特殊的一个系统调用,用于创建子进程,其特殊之处在于其他的系统调用函数一般调用一次返回一次,fork()调用一个返回两次(父进程pid+子进程pid),且fork()调用时返回的子进程pid永远为0

    where?(python中考虑)

    多进程和多线程的共同目标是实现多任务

    任务类型:cpu密集型和io密集型

    cpu密集型:应该使用多进程,充分利用多核cpu实现真正意义上的并发执行

    io密集型:可以使用多线程,节约资源

    how?

    在python中怎样使用多进程和多线程编程?

    多线程

    python对于多线程的支持提供了两个基础库,较为底层的thread模块和较为高层的threading模块

    实现原理:

    将准备并发执行的代码当做参数传递给threading.Thread()创建一个线程对象,结合程序控制结构(循环)等方式来完成此线程对象start()的多次调用,从而实现多线程

    示例代码:(利用多线程实现并发socket通信服务端)

    import threading  ##导入线程库

    import socket    ##导入socket

    s=socket.socket()   #创建socket对象

    s.bind(('0.0.0.0',8888))   #绑定套接字

    s.listen(10)         #监听套接字

    def run():            #定义处理函数

    sock,addr=s.accept()

    while True:

    a=sock.recv(1024)

    if a:

    sock.send(a.upper())

    else:

    sock.close()

    break

    if __name__ =='__main__':

    for i in xrange(20):    #根据for循环创建20个线程

    t=threading.Thread(target=run)   #创建线程对象

    t.start()    #运行线程

    此示例的第二种写法:

    import threading  ##导入线程库

    import socket    ##导入socket

    s=socket.socket()   #创建socket对象

    s.bind(('0.0.0.0',8888))   #绑定套接字

    s.listen(10)         #监听套接字

    class Mythread(threading.Thread):

    def run(self):            #定义处理函数

    sock,addr=s.accept()

    while True:

    a=sock.recv(1024)

    if a:

    sock.send(a.upper())

    else:

    sock.close()

    break

    if __name__ =='__main__':

    for i in xrange(20):    #根据for循环创建20个线程

    t=Mythread()   #创建线程对象

    t.start()    #运行线程

    2.多进程

    python提供可multiprocessing模块中的Process类来创建进程对象,同时该模块还提供了Pool类来创建进程池对象,以及Queue和Pipe实现进程间通信

    实现原理:

    将准备并发执行的代码当做参数传递给multiprocessing.Process()创建一个进程对象,结合程序控制结构(循环)等方式来完成此进程对象start()的多次调用,从而实现多进程

    示例代码:(利用多进程实现并发socket通信服务端)

    import multiprocessing  ##导入线程库

    import socket    ##导入socket

    s=socket.socket()   #创建socket对象

    s.bind(('0.0.0.0',8888))   #绑定套接字

    s.listen(10)         #监听套接字

    def run():            #定义处理函数

    sock,addr=s.accept()

    while True:

    a=sock.recv(1024)

    if a:

    sock.send(a.upper())

    else:

    sock.close()

    break

    if __name__ =='__main__':

    for i in xrange(20):    #根据for循环创建20个线程

    t=multiprocess.Process(target=run)   #创建线程对象

    t.start()    #运行线程

    //可以使用ps aux | grep python 查看已经运行了20个进程

    同上:也可以自定义类并继承Process类再实例化对象的方式进行编写

    总结:对于多任务的情形,并发是不可避免的问题,多进程和多线程可以实现并发,但是由于其都有不可避免的缺陷,所以如何让单进程或单线程实现并发任务的处理,如nginx,就需要使用异步IO的机制,基于事件驱动,在python中实现此机制的称为协程。

    展开全文
  • 文章目录 前言 多线程多进程 多线程 多进程 协程 总结 异步 基本概念 异步编程 asyncio aiohttp 异常 常见异常 异常处理 自定义异常 lambda表达式 lambda表达式用法 高阶函数 functools itertools 无穷迭代器 最短...
  • Python 多进程多线程混合情况下logging模块死锁问题死锁问题复现原因详解解决办法:绕过这个问题注意 死锁问题复现 在使用多线程多进程混杂使用的情况下,有时启动多进程不成功,如下所示: from ...
  • 在TCP/IP协议中,“IP地址+TCP/UDP端口号”表示唯一网络通信中的一个进程,IP地址+端口号称为socket。 注意: 字节序有大端和小端,在两台使用不同字节序的主机上通信,为了让两台主机间能正确的通信,发送端总是把...
  • Python笔记:多线程多进程 0. 引言 1. 多线程 1. 多线程的定义与应用场景 2. 多线程的基本用法 3. 多线程中队列的使用 4. 多线程中锁的应用 2. 多进程 1. 多进程的定义与应用场景 2. 多进程的基本用法 3. ...
  • 虽然与进程相比,线程是一种相对轻量级的工具,但其创建、关闭依然需要消费相当的资源。 如果高频率的创建、关闭线程,对系统性能的影响依旧十分明显的。 为解决此问题,我们可以使用JDK提供的工具——线程池。 ...
  • 不知道有没有小伙伴和我一样,对进程线程对概念一直很模糊,说不太清楚,知道一些,反正就是那么回事?模糊的记得进程是一个独立的程序,线程是cpu运行的单位。上面说的又对又不对,都是很片面的且不准确的,我想...
  • socket在TCP/IP协议中,“IP地址+TCP/UDP端口号”表示唯一网络通信中的一个进程,IP地址+端口号称为socket。 注意: 字节序有大端和小端,在两台使用不同字节序的主机上通信,为了让两台主机间能正确的通信,发送...
  • 那么对于大多数人(尤其是我这样的菜鸟),一个比較快捷的方法便是选择MFC多线程:AfxBeginThread或者CreateThread来进建立多线程。当一两个线程还是能够得。当有3个或者3个以上的线程出现时,极可能出现内存泄漏。...
  • 线程进程

    2021-03-31 15:48:59
    后来业务拓展了,你雇佣了几个工人,这样,你的物业公司就可以同时为多户人家提供服务了——这叫多线程,你是主线程。 工人们使用的工具,是物业管理公司提供的,这些工具由大家共享,并不专属于某一个人——这叫...
  • Python 为什么推荐使用多进程而不是多线程?谈谈python的GIL,多线程多进程1、GIL是什么?GIL的全称是Gloobal Interpreter Lock(全局解释器锁),来源是python设计之初考虑,为了数据安全所做的决定。2、每个CPU在...
  • 线程进程1.1 进程进程进程线程二者对比1.2 并行与并发并发并行二者对比应用同步和异步的概念1) 设计2) 结论2.java线程2.1 创建和运行线程方法一,直接使用 Thread方法二,使用 Runnable 配合 Thread小结方法三,...
  • Linux多线程编程

    千次阅读 2022-01-06 19:22:58
    线程同步: 多线程环境中,无论调度顺序怎么样,都能得到我们想要的结果 同步的方法: 信号量、互斥锁、条件变量、读写锁 互斥锁只能用于互斥型场景,它的作用等同于二值(0/1)信号量的作用 pthread_create:创建并...
  • 我还想要wget和curl的多线程替代品,而不是运行多个此类实例的脚本的一些混用。因此,我进行了进一步搜索,发现我现在所认为的是最终的最现代的多线程CLI下载器​​-aria2。 axel的最大问题是’faked’通过SSL下载...
  • 多线程与信号

    千次阅读 2019-04-11 10:10:38
    在一个单进程中,信号会打断进程的执行,并且递送到进程中处理,而对于多线程环境,信号会递送给其中的一个线程,这个被递送的线程是不确定的。每个线程存在自己的信号屏蔽字,可以通过如下函数设置: int pthread_...
  • 由于tornado很方便地支持多进程模型,多进程的使用要简单很多,在以上例子中,只需要对启动部分稍作改动即可。具体代码如下所示: if __name__ == "__main__": tornado.options.parse_command_line() app = ...
  • 1.多线程相关的三组概念: 1.程序和进程 1.进程(process): 进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。程序是指令、数据及其组织形式的描述,进程是程序的实体。...
  • 文章目录软件构造知识点总结(三)-Java多线程与线程安全一、进程与线程二、Java多线程的实现1.继承Thread类2.实现Runnable接口3.实现Runnable接口的优势三、线程的状态四、线程的调度五、线程安全1.Java内存模型2....
  • 进程(Process)是具有一定独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的一个独立单位。程序只是一组指令的有序集合,它本身没有任何运行的含义,只是一个静态实体。...线程(Thre...
  • 微信h5棋牌架设(aqiulian.com)多线程多进程服务器的实现,完整的微信h5棋牌架设,搭建教程联系方式: QQ:212303635. socket 在TCP/IP协议中,“IP地址+TCP/UDP端口号”表示唯一网络通信中的一个进程,IP地址+...
  • 1.多线程技能 1.什么是线程?在进程中独立运行的子任务。 2.多线程优点?可以大幅利用CPU的空闲时间来处理其他任务。 3.什么场景使用多线程? 1.阻塞 2.依赖。 注: 1.多线程是异步的。线程被调用时机是随机的。 2....
  • 【自己的总结】 package dc.stock; import dc.stock.policies.StockP1_1_... * 之所以单独列出来,是为了多线程的使用; */ public class MainRunStockPolicy { public static void main(String[] args...
  • Python TimedRotatingFileHandler 多进程环境下的问题和解决方法 原文:https://my.oschina.net/lionets/blog/796438 Python 自带了一个 handler 可以实现每天自动切割日志文件的功能(其实支持各种按时间切割的...
  • 文章目录1. 互斥锁(mutex)基本概念2. 互斥量的用法(1)lock(),unlock()(2)用lock和unlock改写上一节最后的代码(3)std::lock_guard类模板3. 死锁(1)死锁演示(2)死锁的...其他线程只能等这个线程处理完,解
  • 线程进程有什么区别?可以说是程序员必须准备的一道高频面试题。相信不少程序员在面试算法或开发岗位时都遇到过这个问题。尽管这个问题似乎每个接触过计算机操作系统的人都应该懂,但是如何能回答好这个问题却十分...
  • Python多线程记录

    2022-04-30 16:06:18
    那么使用多线程会对我们这个这系统造成什么影响呢,主要还是多线程造成的混用问题吧: 这里我贴出程序吧,这样方便进行测试: import threading g_num = 0 def work1(num): global g_num for i in range(num): g_num...
  • 线程仅仅被视为一个与其他进程共享某些资源的进程,而是否共享地址空间几乎是进程和 Linux 中所谓线程的唯一区别。线程创建的时候,加上了 CLONE_VM 标记,这样 线程的内存描述符 将直接指向 父进程的内存描述符。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,599
精华内容 2,239
关键字:

多进程多线程混用