原文:https://www.cnblogs.com/yorkyang/p/7804733.html

线程的优点:

  • 减少系统调度开销,不占有独立的资源,切换速度快,执行效率高。
  • 线程间通信方便,可共享资源。
  • 改善程序设计结构,功能复杂的进程可以分为多个独立的线程分别执行,模块性更强。

  线程分为:用户态线程和核心态线程。

  用户态的多线程程序在运行时不许要特定的内核支持,同一个进程的线程之间进行切换时,不需要调用系统调用。

  核心态线程的实现方法允许不同进程中的的线程按照相同的调度方法进行调度,有利于发挥多处理器的并发优势。

线程创建:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*),void *arg);
//thread 指向线程标识符的指针,使用这个标识符来引用新线程
//attr 设置线程属性,设为NULL则生成默认属性的线程
//start_routine 线程运行函数的起始位置
//arg 线程运行函数的参数

线程终止:

1.通过线程自身结束

void pthread_exit(void *rval_ptr);
//rval_ptr是函数的返回代码,相当于线程的退出码 2.通过同一进程的其他线程来结束 int pthread_cancel(pthread_t tid);
//tid是要结束线程的标识符

下面的函数用于阻塞等待一个线程的结束

int pthread_join(pthread_t thread, void **return_ptr)
//创建线程,输出当前系统的时间

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<unistd.h>
#include<pthread.h> void print_currentTime(void)
{
time_t ct;
ct=time(NULL);
//ctime:将秒数转换成字符串
printf("current time is : '%s'",ctime(&ct));
pthread_exit("Time thread finished!\n");
} int main()
{
int ret;
void *thread_result;
pthread_t new_thread; ret=pthread_create(&new_thread,NULL,(void*)print_currentTime,NULL);
if(ret!=0){
perror("thread creation failed!\n");
exit(EXIT_FAILURE);
} printf("waiting for new thread....\n");
ret=pthread_join(new_thread,&thread_result);
if(ret!=0){
perror("thread join failed!\n");
exit(EXIT_FAILURE);
} printf("thread joined, returned: %s\n",(char*)thread_result);
return 0;
}
//编译时候注意: gcc thread_date.c -o thread_date -lpthread

线程属性:

线程属性主要包括分离属性,绑定属性,调度属性,堆栈属性,继承属性等,结构为pthread_attr_t。

属性设置函数:

int pthread_attr_init(pthread_attr_t *attr)
//attr是指向属性结构的指针
//注意:此函数必须在调用pthread_creater()函数之前调用

这里提到了一个概念“轻进程(Light Weight Process, LWP)”,位于用户层与系统层之间的内核线程。系统对线程资源的分配以及对线程的控制是通过轻进程来实现的,一个轻进程可以控制一个或多个线程。

获取线程绑定状态函数:

int pthread_attr_getscope(pthread_attr_t *attr, int *scope)
//scope返回绑定属性的状态

设置线程绑定属性函数:

int pthread_attr_setscope(pthread_attr_t* attr, int scope)
//scope是要绑定的类型

获得线程优先级函数:

int pthread_attr_getschedparam(pthread_attr_t *attr, const struct sched_param *param)
//param中存放线程的调度参数信息

设置线程优先级函数:

int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param)

获取调度策略函数:

int pthread_attr_getschedpolicy(pthread_attr *attr, int *policy)
//调度策略存放在policy中

设置调度策略函数:

int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)

获取并发级别函数:

int pthread_getconcurrency(void)

设置并发级别函数:

int pthread_setconcurrency(int new_level)

多线程同步技术:

线程同步机制主要有:互斥量,信号量,条件变量,读写锁等。

互斥量:

数据类型为pthread_mytex_t,主要函数:

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
int pthread_mutex_lock(pthread_mutex_t *mutex); //阻塞调用
int pthread_mutex_trylock(pthread_mutex_t *mutex); //非阻塞调用
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
//mutex是定义的pthread_mutex_t的指针,mutex_attr是互斥量的属性结构

例子:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<string.h> pthread_mutex_t mutex;
int count=0;
char msg_buf[64]; void setMsg_Func(void)
{
while(count>0){
pthread_mutex_lock(&mutex);
memset(msg_buf,0,64);
sprintf(msg_buf,"count=%d.\n",count--);
pthread_mutex_unlock(&mutex);
srand((int)time(0));
sleep(rand()%3);
}
pthread_exit(0);
} void printMsg_Func(void)
{
while(count>=0){
pthread_mutex_lock(&mutex);
printf("%s",msg_buf);
pthread_mutex_unlock(&mutex);
if(0==count)
break;
srand((int)time(0));
sleep(rand()%3);
}
} int main()
{
int ret;
pthread_t set_thread;
count=4;
pthread_mutex_init(&mutex,NULL);
ret=pthread_create(&set_thread,NULL,(void*)&setMsg_Func,NULL);
if(ret!=0){
perror("thread creation failed!\n");
exit(EXIT_FAILURE);
} printMsg_Func();
ret=pthread_join(set_thread,NULL);
if(ret!=0){
perror("thread creation failed!\n");
exit(EXIT_FAILURE);
}
printf("Finished!\n");
pthread_mutex_destroy(&mutex);
return 0;
}

但是要注意,如果使用互斥量过程中,如果两个线程试图同时占用两个资源,并锁定,可能造成死锁。

条件变量:

  只使用互斥量很可能造成死锁,为此可以加入条件变量。条件变量允许线程阻塞和等待另一个线程发送信号,使用条件变量可以以原子方式阻塞线程,直到满足某个条件为止。

  互斥量主要用来保证对临界区的互斥进入,而条件变量则用于线程的阻塞等待。

int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);     //创建条件变量
int pthread_cond_signal(pthread_cond_t *cond); //用来释放被阻塞在条件变量cond上的进程
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); //使线程阻塞
int pthread_cond_broadcast(pthread_cond_t *cond); //用来唤醒所有阻塞在条件变量cond上的线程
int pthread_cond_timewait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
//使线程阻塞,与wait不同,它经过abstime时间后,无论条件是否满足,都会释放 int pthread_cond_destroy(pthread_cond_t *cond); //cond是一个指向结构pthread_cond_t的指针
//cond_attr是条件变量的属性结构指针

例子:

//创建两个线程,偶数时进程1给变量加1,奇数时进程2给变量加1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h> #define MAX_COUNT 9 pthread_mutex_t mutex;
pthread_cond_t cond;
int count=0; void addCount_odd_Func(void)
{
pthread_mutex_lock(&mutex);
while(count<MAX_COUNT){
if(count%2==1){
count++;
printf("addcout_odd_Func():count=%d.\n",count);
pthread_cond_signal(&cond);
}
else
pthread_cond_wait(&cond,&mutex);
}
pthread_mutex_unlock(&mutex);
} void addCount_even_Func(void)
{
pthread_mutex_lock(&mutex);
while(count<MAX_COUNT){
if(count%2==0){
count++;
printf("addCount_even_Func:count=%d.\n",count);
pthread_cond_signal(&cond);
}
else
pthread_cond_wait(&cond,&mutex);
}
pthread_mutex_unlock(&mutex);
} int main(int argc, char **argv)
{
int ret;
pthread_t odd_thread,even_thread;
pthread_attr_t thread_attr;
count=0; pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
ret=pthread_attr_init(&thread_attr);
if(ret!=0){
perror("attribute creation failed!");
exit(EXIT_FAILURE);
} pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_DETACHED); ret=pthread_create(&odd_thread,&thread_attr,(void*)&addCount_odd_Func,NULL);
if(ret!=0){
perror("thread creation failed!");
exit(EXIT_FAILURE);
} ret=pthread_create(&even_thread,&thread_attr,(void*)&addCount_even_Func,NULL);
if(ret!=0){
perror("thread creation failed!");
exit(EXIT_FAILURE);
} while(count<MAX_COUNT); printf("Finished!");
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&mutex); return 0;
}

C语言中的多线程的更多相关文章

  1. C语言中的多线程编程

    很久很久以前,我对C语言的了解并不是很多,我最早听说多线程编程是用Java,其实C语言也有多线程编程,而且更为简单.方便.强大.下面就让我们简单领略一下Unix C语言环境下的多线程编程吧! 下面先看 ...

  2. C语言中关键字volatile的含义【转】

    本文转载自:http://m.jb51.net/article/37489.htm 本篇文章是对C语言中关键字volatile的含义进行了详细的分析介绍,需要的朋友参考下 volatile 的意思是“ ...

  3. C/C++——C++变量的作用域与生命周期,C语言中变量的作用域和生命周期

    全局变量 作用域:全局作用域(全局变量只需在一个源文件中定义,就可以作用于所有的源文件.) 生命周期:程序运行期一直存在 引用方法:其他文件中要使用必须用extern 关键字声明要引用的全局变量. 内 ...

  4. Java中的多线程总结(转)

      1.多线程概述 当一个程序运行时,内部可能包含了多个顺序执行流,每个顺序执行流就是一个线程.主要以下几个优点: 线程之间很容易实现共享内存 创建线程代价较小 Java语言内置多线程功能支持 2.线 ...

  5. Go语言中的管道(Channel)总结

    管道(Channel)是Go语言中比较重要的部分,经常在Go中的并发中使用.今天尝试对Go语言的管道来做以下总结.总结的形式采用问答式的方法,让答案更有目的性. Q1.管道是什么? 管道是Go语言在语 ...

  6. C语言中关键字auto、static、register、const、volatile、extern的作用

    原文:C语言中关键字auto.static.register.const.volatile.extern的作用 关键字auto.static.register.const.volatile.exter ...

  7. OS X 和iOS 中的多线程技术(下)

    OS X 和iOS 中的多线程技术(下) 上篇文章中介绍了 pthread 和 NSThread 两种多线程的方式,本文将继续介绍 GCD 和 NSOperation 这两种方式.. 1.GCD 1. ...

  8. 【worker】js中的多线程

    因为下个项目中要用到一些倒计时的功能,所以就提前准备了一下,省的到时候出现一下界面不友好和一些其他的事情.正好趁着这个机会也加深一下html5中的多线程worker的用法和理解. Worker简介 J ...

  9. C语言编程(多线程)

    C语言中多线程编程包括的文件:#include<pthread.h>(linux环境下) pthread_t //线程函数返回类型 pthread_mutrex_t //互斥锁类型 int ...

随机推荐

  1. 3_PHP表达式_3_有关变量或常量状态的函数

    以下为学习孔祥盛主编的<PHP编程基础与实例教程>(第二版)所做的笔记. 1. 数据类型查看函数 PHP为变量或常量提供了查看数据类型的函数,其中包括gettype()和var_dump( ...

  2. Go net/http 发送常见的 http 请求

    使用 golang 中的 net/http 包来发送和接收 http 请求 开启 web server 先实现一个简单的 http server,用来接收请求 package main import ...

  3. 前端知识总结--ES6新特性

    ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了.它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应 ...

  4. 关于http的小知识

    http客户端发起请求,创建端口 http服务器在端口监听客户端请求 http服务器向客户端返回状态和内容 浏览器: 1.Chrome搜索自身的DNS缓存 2.搜索操作系统自身的DNS缓存(浏览器没有 ...

  5. Qt槽函数创建

    法一 手动添加 private slots: void on_cancel_clicked(); void Widget::on_cancel_clicked() { } connect(ui-> ...

  6. linux跳板机开发之trap信号机应用

    场景1:公司新招聘了一个配置管理员,他的工作是负责将公司开发人员写的新代码依次分发到办公室测试环境.IDC测试环境和正式线上环境.因此公司需要开发一个程序,当配置管理员登录服务器,只能进入分发的管理界 ...

  7. 【DRF框架】视图组件

    基于mixins视图类 from rest_framework import mixins # 创建视图 class CreateModelMixin(object) def create(self, ...

  8. Linux命令——ls

    15 Interview Questions on Linux “ls” Command – Part 1 10 Useful ‘ls’ Command Interview Questions – P ...

  9. jupyter notebook在启动时kernel一直在busy , 无法print

    转: https://blog.csdn.net/loovelj/article/details/82184223 一. 问题: 内核一直显示忙碌,连简单的print都不能执行了.然后看后台,最后说” ...

  10. P1005 矩阵取数游戏[区间dp]

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的\(m*n\)的矩阵,矩阵中的每个元素\(a_{i,j}\)均为非负整数.游戏规则如下: 每次取数时须从每行各取走一个元素,共n个.经过m次后 ...