多线程总结上

虚拟计时器 : 进程状态是R 用户态的运行时间
实用计时器  :进程状态是R 用户态和内核态的总运       
                      行时间
——————————————————
多线程   协程
上下文:进程执行的线程
上下文切换:进程打开的标准输入、标准输出和错误输出,当切换到另一个进程时,需要进行压栈(即压入内存),把一个进程的现场保存下来,然后去执行另外一个进程的现场
    线程通常叫做轻量级进程。即线程都在一个进程中,当写一个二进制执行起来时,其本身就是一个线程,这里这个进程中只有一个线程。假如创建了多个线程,则他们共享内存地址空间,如在一个线程中malloc堆内存,则在另一个线程中就可以直接拿这个p去访问堆内存 ,是一个更加接近于执行体的概念(它只能去读每一条代码,其它东西都是跟别人共享的,不过它有局部变量,类似于在C语言中局部变量只在其最近的大括号中有效,所以线程唯一拥有的就是其栈空间(自动分配的)),拥有独立的执行序列(即各自走各自的代码),是进程的基本调度单元,每个进程至少都有一个 main 线程。它 与同进程中的其他线程共享进程空间{堆 代码(代码段) 数据 文件描述符 信号等},大大减少了上下文切换的开销

700ms  进程启动时间
1ms    线程启动时间

线程和进程在使用上各有优缺点: 线程执行开销小,占用的CPU少,线程之间的切换快,但不利于资源的管理和保护(如线程在操作堆内存,如踩内存,结果别人去访问自己的内存时被踩了,这时所有的线程都崩溃。即任何一个线程出错,其它任何线程都挂掉。因为踩到异常之后,系统会给进程发一个信号,这时每个线程都会接收到SIGSEGV信号);而进程正相反。从可移植性来讲,多进程的可移植性要好些(因为出 问题 更容易分析)
要注意的是,由于线程共享了进程的资源和地址空间,因此,任何线程对系统资源的操作都会给其他线程带来影响。(所以不要发进程信号)除了栈空间,其它都是共享的


线程调试难度更大,凡涉及到内存的东西,gdb调试不好使,一般采用打印的方式来调试

4G进程地址空间最上面一段是内核映射过来的(不是内核实际地址),内核中的线程可以看到它的所有物理内存

线程创建的Linux实现
Linux的线程是通过用户级的函数库实现的,一般采用pthread线程库实现线程的访问和控制。它用第3方posix标准的pthread,具有良好的可移植性。  编译的时候要在后面加上 –lpthread
                   创建                 退出                等待
多进程         fork()                 exit()               wait()
多线程   pthread_create   pthread_exit()   pthread_join()

创建线程实际上就是确定调用该线程函数的入口点(通过pthread函数,把函数的名字传给pthread,这时线程启动时就知道自己从哪里开始,即从哪个函数开始,而该函数就是线程的入口点,如果多个线程都用相同函数入口点也无所谓,因为他们本身就是并行执行的(可以并发),创建后就放在一个就绪队列,这时通过分时间片往下执行 ),线程的创建采用函数pthread_create。在线程创建以后,就开始运行相关的线程函数,在该函数(即线程入口函数a)运行完之后,线程就退出(a{可以调用很多层函数,所有代码都在尾括号内就行}的结尾括号一结束,线程就结束了),这也是线程退出的一种方式。另一种线程退出的方式是使用函数pthread_exit()函数,这是线程主动退出行为。这里要注意的是,在使用线程函数时,不能随意使用exit退出函数进行出错处理,由于exit的作用是使调用进程终止,往往一个进程包括了多个线程,所以在线程中通常使用pthread_exit函数来代替进程中的退出函数exit。
pthread_join 函数可以用于将当前线程挂起,等待线程的结束。这个函数是一个线程阻塞函数,调用它的函数将一直等待直到被等待的线程结束为止,当函数返回时,被等待线程的 资源被回收。

函数原型:

#include <pthread.h>


int pthread_create(pthread_t* thread, pthread_attr_t * attr, void *(*start_routine)(void *), void * arg);
void pthread_exit (void *retval);

通常的形式为:

pthread_t pthid;

pthread_create(&pthid,NULL,pthfunc,NULL);pthread_create(&pthid,NULL,pthfunc,(void*)3);

pthread_exit(NULL);pthread_exit((void*)3);//3作为返回值被pthread_join函数捕获,然后清理系统资源。

函数pthread_create用来创建线程。返回值:成功,则返回0;失败,则返回-1。各参数描述如下:

·参数 thread 是传出参数,保存新线程的标识
线程ID:先定义一个整型ID,然后把地址放过来:pthread_t  th;    &th;
进程中用fork

·参数attr是一个结构体指针,结构中的元素分别指定新线程的运行属性,attr可以用pthread_attr_init等函数设置各成员的值,但通常传入为NULL 即可;


·参数 start_routine 是一个函数指针指向新线程的入口点函数,线程入口点函数带有一个 void * 的参数由 pthread_create 的第4个参数传入
传入参数、返回值都为指针的函数指针(即线程函数,函数名本身为地址)。该位置直接写函数名,其函数定义:
void* thread_enter(void* p)
{
   系统内部来调用这个函数的, 执行完这个函数,线程就结束了
}

·参数arg用于传递给第3个参数指向的入口点函数的参数,可以为NULL,表示不传递

函数 pthread_exit 表示线程的退出。其参数可以被其它线程用 pthread_join 函数捕获。

在编译多线程程序时,需要在后面加上 -lpthread,之前的库是在libc.so,而线程pthread的库文件不在这里,需要自己引入
ps -elLf  :查看创建的线程

在多线程程序中,如果返回值正确,但程序不能达到预期,则检查是否加上pthread_exit();或者是否加上头文件
在进程中,主进程和子进程都是独立的,而主线程和子线程共享除了栈空间之外的所有资源,故在主线程中需要缓冲时间(while or sleep)来等待子线程(因为主线程一旦结束,进程就结束了,资源被回收。所以实际使用是在主线程中加while),但子线程之间则不需要缓冲时间

3.3.线程终止清理函数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Python的多线程可以使用内置的`threading`模块来实现。这个模块提供了一些对象和方法,可以方便地创建和管理线程。 以下是一个简单的多线程示例,它创建了两个线程,每个线程都打印数字1到5: ```python import threading def print_numbers(): for i in range(1, 6): print(threading.current_thread().name, i) # 创建两个线程 t1 = threading.Thread(target=print_numbers) t2 = threading.Thread(target=print_numbers) # 启动线程 t1.start() t2.start() # 等待线程结束 t1.join() t2.join() print("All threads have finished.") ``` 在这个示例中,我们首先定义了一个`print_numbers()`函数,它用于打印数字1到5,并且在每个数字前面打印线程的名称。然后,我们创建了两个线程`t1`和`t2`,它们都指向`print_numbers()`函数。接下来,我们启动这两个线程,并等待它们完成,最后输出"All threads have finished."。 注意,`threading.current_thread().name`用于获取当前线程的名称。在这个示例中,我们没有指定线程的名称,因此它们将默认为"Thread-1"和"Thread-2"。 多线程可以提高程序的执行效率,但是也需要注意线程安全问题,比如并发访问共享变量可能会导致数据不一致的问题。因此,在编写多线程程序时,需要特别注意线程安全问题。 ### 回答2: Python多线程是指在一个程序中同时执行多个线程,每个线程都可以独立执行不同的任务。Python的多线程是基于线程模块实现的,通过创建多个线程对象来实现多线程的功能。 Python多线程的使用需要导入threading模块,使用threading.Thread类来创建线程对象。通过调用线程对象的start()方法,线程就会开始执行。线程可以是执行同一个函数,也可以是执行不同的函数,甚至可以是执行不同的类的方法。 线程之间可以共享全局变量,但需要避免多个线程同时修改全局变量的情况,可以通过互斥锁机制来保证数据的一致性。 Python多线程的优点是能够提高程序的执行效率,特别是在IO操作较多的情况下,多线程可以充分利用CPU的空闲时间。另外,多线程还可以实现一些并发的功能,例如同时下载多个文件、同时处理多个网络请求等。 然而,Python的多线程在处理CPU密集型任务上并不适用,因为在Python中,多线程并不能利用多核CPU的优势,由于Python的GIL(全局解释器锁)机制,多线程在CPU密集型任务上的效率并不比单线程高。 总结来说,Python的多线程适用于IO密集型任务,能够提高程序的执行效率和实现并发的功能,但对于CPU密集型任务,单线程可能更适合。 ### 回答3: Python 多线程是指在一个程序中同时运行多个线程,每个线程独立执行其任务。Python 中的多线程可以通过使用 threading 模块来实现。 在 Python 中,多线程的主要优势是能够提升程序的执行效率。通过多线程,可以将耗时较长的任务分配给不同的线程来并行执行,从而缩短程序的总执行时间。这尤其适用于那些需要频繁进行网络请求、IO 操作或者计算密集型任务的程序。 使用 Python 的 threading 模块可以很方便地创建和管理线程。通过创建 Thread 对象并传入要执行的函数,就可以创建一个新的线程。可以使用 start() 方法来启动线程,并使用 join() 方法来等待线程执行完成。 需要注意的是,Python 中的多线程并不能真正实现并行执行,而是通过在不同任务之间快速切换来模拟并行。这是由于 Python 的全局解释器锁(GIL)的存在,它使得同一时间只有一个线程能够执行 Python 的字节码。因此,在计算密集型任务上,使用多线程并不能获得真正的并行加速。 另外,多线程在处理共享资源时需要注意线程安全问题。多个线程同时访问和修改共享数据可能会导致数据不一致或者竞争条件。在这种情况下,可以通过使用锁(Lock)等同步机制来确保数据的正确访问和更新。 总而言之,Python 多线程可以提升程序的执行效率,适用于需要进行网络请求、IO 操作或者并发处理的任务。然而,在计算密集型任务上,并不能实现真正的并行加速。同时,在处理共享资源时需要注意线程安全问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值