线程详解

线程的基本概念:

1.线程在Linux下是轻量级的进程,同一程序中的线程会共享同一份全局内存区,包括代码段(.text),数据段(.bss,.data),堆段;但是每一个线程都有自己独立的栈段。所有的线程栈都驻留在同一块虚拟内存。

线程的基本API

启动程序时产生的进程是单条线程,也叫主线程

1.创建线程

    #1:传出参数,表示线程的id号

    #2:线程的基本属性(唯一接触到的是分离属性后面讲解)

    #3:线程创建后所要执行的函数,该函数返回值为void* 不能够接受成员函数除非是静态成员函数(不包含this指针)

    #4:该函数传入的参数,可以是结构体

注意:图中编译和链接需要指定参数  eg: gcc -o create pthread_create.c -pthread

2.退出线程

    #1:该参数是一个传入参数,如果你想赋予该线程退出状态;但是必须是一个全局变量,否者如果线程返回,局部变量空间将释放,获取到的线程退出状态未知。

不论是主线程还是子线程,都是平等地位,任意一方调用该函数退出(不包括任意一个线程调用exit()或在main()中调用return),其余的线程将正常运行。

3.回收线程


    #1:要释放的线程的id(不能释放任意的线程,只能是你知道线程id)

    #2:传出参数,获取所链接线程的退出状态。

线程之间平等,任意双方都可以互相join,如果未能join那么线程退出后将变成僵尸线程,浪费系统资源。

4.设置分离属性

    我们应当在线程一创建就将其设置为分离的(主线程与新线程没有关系),这样新创建的线程就可以自动释放,并且不能够再调用pthread_join();

线程同步

1.线程的安全问题

    线程间虽然通信方便但是可能会导致多个线程访问同一变量,引出临界区:某一共享资源的代码片段。造成线程同步机制的本质就是线程在同一块虚拟内存空间中工作。

    1.静态的互斥锁变量

        pthread_mutex_t  mtx = PTHREAD_MUTEX_INITIALIZER;

    2.动态创建锁变量

        

        pthread_mutex_init();

        #1:操作的锁变量

        #2:锁变量的属性,如果为NULL则是默认属性

        pthread_mutex_destory();

    

    3.加锁与解锁

        pthread_mutex_lock(&mtx);

        pthread_mutex_unlock(&mtx);

2.互斥量的死锁

    如果一个线程同时访问两个或多个临界区资源,同时有两个或多个线程操作锁变量,可能产生死锁。

一个线程锁住mtx1,但是需要mtx2;另一个线程同时锁住mtx2,但是需要mtx1,这两个线程将无限期的等待下去。

解决方法:

    1.按层级操作锁变量,任何一个线程必须先锁mtx1,再锁mtx2。这样不会产生死锁

    2.无需遵循层级规则,当一个线程锁住mtx1时,调用pthread_mutex_trylock();如果返回错误,释放所有的锁变量。

  1 #include<pthread.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<stdio.h>
  5 
  6 int number = 0;
  7 void printids(const char* s)
  8 {
  9     pid_t pid;
 10     pthread_t tid;
 11     pid = getpid();
 12     tid = pthread_self();
 13     printf("%s pid %lu tid %lu\n",s,pid,tid);
 14 }
 15 
 16 void* thr_fn()
 17 {
 18     printids("new tids:");
 19     return ((void*)0);
 20 }
 21 
 22 int main()
 23 {
 24     pthread_t ntid;
 25     int err = 0;
 26 
 27     err = pthread_create(&ntid, NULL, thr_fn, NULL);
 28     if(err != 0)
 29     {
 30         perror( "can't create thread");
 31     }
3.条件变量

    条件变量与互斥锁不同,实质上它并不像锁,而是在不满足条件的时候阻塞线程,满足条件时解除阻塞,互斥锁是保护临界区,每次只能由一个线程访问。一般情况下条件变量和互斥锁共同使用。(就不列出条件变量api)

    生产者:


    消费者:


线程安全

使用了所有线程共享的全局变量或静态变量,但是调用函数所访问的变量是安全的。实现线程安全方法:

    1.将互斥量与函数关联起来:实现简单但是会导致多线程访问函数是串行访问,丧失并发性

    2.当函数访问临界区的时候增加互斥量,除非多个线程同时执行临界区代码,否者是并发的。

可以通过调用函数自己定义的缓存区来存储每次的结果,达到线程安全的目的。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python多线程是指在Python程序中同时执行多个线程的编程技术。使用多线程编程具有以下几个优点:首先,线程之间可以共享内存,这使得数据共享和通信更加容易。其次,创建线程的代价比创建进程小得多,因此使用多线程来实现多任务并发执行比使用多进程更高效。此外,Python语言内置了多线程功能支持,简化了多线程编程的复杂性\[1\]。 然而,需要注意的是,在Python 2.x版本中,存在全局解释器锁(GIL),它限制了同一进程中只能有一个线程执行Python字节码。这意味着在多核CPU上,Python的多线程并不能充分利用多核处理器的优势,因为只有拿到GIL锁的线程才能执行\[2\]。 尽管如此,多线程在IO密集型代码中仍然能够提升效率。在涉及文件处理、网络爬虫等需要进行IO操作的任务中,多线程可以避免不必要的IO等待时间,提高程序的执行效率。因此,对于IO密集型代码,Python的多线程是比较友好的\[3\]。 总结起来,Python的多线程编程具有一些优点,但也存在一些限制。在选择是否使用多线程时,需要根据具体的应用场景和需求来进行权衡和选择。 #### 引用[.reference_title] - *1* [python多线详解(超详细)](https://blog.csdn.net/m0_67900727/article/details/123399522)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [python多线详解](https://blog.csdn.net/weixin_39612023/article/details/109945251)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值