您的位置 首页 知识

多线程c语言教程 多线程编程 c语言多线程控制函数

多线程c语言教程 多线程编程 c语言多线程控制函数

文章目录[隐藏]

  • 开门见山说,创建一个线程
  • 第二,线程同步
  • [3]旗语

多线程编程(c++多线程编程)

多线程编程可以说是每个程序员的基本功,也是开发中的难点其中一个。以Linux C为例,介绍了线程的创建和几种常见的线程同步方式。最终对多线程编程进行了拓展资料和思索,并给出了代码示例。

开门见山说,创建一个线程

多线程编程的第一步是创建线程。创建一个线程实际上增加了一个控制进程,使得同一个进程中的多个控制进程并发或并行执行。

创建线程函数。其他功能不在此列。可以参考pthread.h

includeint?pthread_create(????pthread_t?*restrict?thread,??/*线程id*/const?pthread_attr_t?*restrict?attr,????/*线程属性,默认可置为NULL,表示线程属性取缺省值*/void?*(*start_routine)(void*),??/*线程入口函数*/?void?*restrict?arg??/*线程入口函数的参数*/);

代码示例:

includeincludeincludeincludeincludechar*?thread_func1(void*?arg)?????pid_t?pid?=?getpid();????pthread_t?tid?=?pthread_self();????printf(&8220;%s?pid:?%u,?tid:?%u?(0x%x)\n&8221;,?(char*)arg,?(unsigned?int)pid,?(unsigned?int)tid,?(unsigned?int)tid);????char*?msg?=?&8220;thread_func1&8221;;????return?msg;}void*?thread_func2(void*?arg)?????pid_t?pid?=?getpid();????pthread_t?tid?=?pthread_self();????printf(&8220;%s?pid:?%u,?tid:?%u?(0x%x)\n&8221;,?(char*)arg,?(unsigned?int)pid,?(unsigned?int)tid,?(unsigned?int)tid);????char*?msg?=?&8220;thread_func2?&8220;;????while(1)?????????printf(&8220;%s?running\n&8221;,?msg);????????sleep(1);????}????return?NULL;}int?main()?????pthread_t?tid1,?tid2;????if?(pthread_create(&tid1,?NULL,?(void*)thread_func1,?&8220;new?thread:&8221;)?!=?0)?????????printf(&8220;pthread_create?error.&8221;);????????exit(EXIT_FAILURE);????}????if?(pthread_create(&tid2,?NULL,?(void*)thread_func2,?&8220;new?thread:&8221;)?!=?0)?????????printf(&8220;pthread_create?error.&8221;);????????exit(EXIT_FAILURE);????}????pthread_detach(tid2);????char*?rev?=?NULL;????pthread_join(tid1,?(void?*)&rev);????printf(&8220;%s?return.\n&8221;,?rev);????pthread_cancel(tid2);????printf(&8220;main?thread?end.\n&8221;);????return?0;}

第二,线程同步

有时候我们需要多个线程相互配合执行,接着需要线程之间的同步。线程同步的常用技巧有:

互相排斥

旗语

条件变量

让我们看一个没有线程同步的例子:

includeincludeincludeincludeincludedefine?LEN?100000int?num?=?0;void*?thread_func(void*?arg)?????for?(int?i?=?0;?in;????????????????struct?data*?tmp?=?phead;????????????????phead?=?phead->next;????????????????free(tmp);????????????}????????}????????pthread_mutex_unlock(&mlock);????????if?(count?>?LIMIT)????????????break;????}????printf(&8220;consumer?count=%d\n&8221;,?count);}int?main()?????pthread_t?tid1,?tid2;????pthread_create(&tid1,?NULL,?(void*)producer,?NULL);????pthread_create(&tid2,?NULL,?(void*)consumer,?NULL);????????pthread_join(tid1,?NULL);????pthread_join(tid2,?NULL);????return?0;}

分享更多关于Linux后端开发网络底层原理的聪明。点击跳转,提升技术栈。内容聪明点有Linux、Nginx、ZeroMQ、MySQL、Redis、线程池、MongoDB、ZK、Linux内核、CDN、P2P、epoll、Docker、TCP/IP、coroutine、DPDK等等。

点击完整视频链接:C/C++Linux服务器开发/后台架构师零音学院-进修视频教程-腾讯课堂

条件变量中的执行逻辑:

关键是要明白执行到int pthread _ cond _ wait(pthread _ cond _ t * restrict cond,pthread _ mutex _ t * restrict mutex)时会发生什么。其他的都比较好领会。在执行这个函数之前,需要获取互斥锁,判断是否满足条件,如果满足执行条件,继续向下执行,释放锁;如果判断不满足执行条件,则释放锁,线程在此被阻塞。等到其他线程通知满足执行条件,唤醒线程,再次锁死,向下执行后释放锁。(简而言之:解锁->阻塞等待->唤醒后锁定返回)

上面的示例可能很乏味,但下面的代码示例更简洁:

includeincludeincludeincludeincludeincludeincludedefine?NUM?3pthread_cond_t?condv?=?PTHREAD_COND_INITIALIZER;pthread_mutex_t?mlock?=?PTHREAD_MUTEX_INITIALIZER;?void?producer(void*?arg)?????int?n?=?NUM;????while(n&8211;)?????????sleep(1);????????pthread_cond_signal(&condv);????????printf(&8220;producer?thread?send?notify?signal.?%d\t&8221;,?NUM-n);????}}void?consumer(void*?arg)?????int?n?=?0;????while?(1)?????????pthread_cond_wait(&condv,?&mlock);????????printf(&8220;recv?producer?thread?notify?signal.?%d\n&8221;,?++n);????????if?(NUM?==?n)?????????????break;????????}????}}int?main()?????pthread_t?tid1,?tid2;????pthread_create(&tid1,?NULL,?(void*)producer,?NULL);????pthread_create(&tid2,?NULL,?(void*)consumer,?NULL);????????pthread_join(tid1,?NULL);????pthread_join(tid2,?NULL);????return?0;}

运行结局:

producer?thread?send?notify?signal.?1???recv?producer?thread?notify?signal.?1producer?thread?send?notify?signal.?2???recv?producer?thread?notify?signal.?2producer?thread?send?notify?signal.?3???recv?producer?thread?notify?signal.?3

[3]旗语

信号量适用于控制只支持有限数量用户的共享资源。用于将计数值保持在0和指定的最大值之间。当线程完成一次对信号量对象的等待时,计数值减一;当线程完成释放信号量对象一次时,计数值增加1。当计数值为0时,线程挂起并等待,直到计数值超过0。

主要功能如下:

include?int?sem_init(sem_t?*sem,?int?pshared,?unsigned?int?value);int?sem_wait(sem_t?*sem);int?sem_trywait(sem_t?*sem);int?sem_post(sem_t?*?sem);int?sem_destroy(sem_t?*?sem);

代码示例如下:

includeincludeincludeincludeincludeincludeincludeincludedefine?NUM?5int?queue[NUM];sem_t?psem,?csem;?void?producer(void*?arg)?????int?pos?=?0;????int?num,?count?=?0;????for?(int?i=0;?i