多线程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