在将线程之前就不得不再讲一下进程
进程与线程之间的关系
进程是资源分配的最小单位,线程是程序执行的最小单位,进程可以看做是一个控制线程,一个进程在同一时间只能做同一件事,而有多个控制线程,就能在同一时间做不同的事。一个线程属于一个进程,而一个进程可以有多个线程。进程是程序化的实例,是担当分配系统资源的基本单位,是分配系统资源的基本单位,一条线程指的是进程中一个单一顺序的控制流。线程包含了进程内执行环境必须的信息。
使用线程的原因
1,和进程相比线程所需要的资源更少,每开辟一个进程就需要分配给他独立的地址空间,建立众多的数据表来维护它的代码段,堆栈段和数据段
2,对于进程来说他们有独立的数据空间,要进行数据传递必须通过通信的方式,而线程由于在同一进程下共享数据空间,所以一个线程可以为其他线程直接所用
3,多线程是一种多任务,并发的工作方式
Linux上线程开发API
Linux常用线程库 pthread,多线程开发的基本思想:线程,互斥锁,条件
线程
线程创建 ,退出,等待
函数原型:
#include <pthread.h>
int pthread_creat(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
//成功返回0,失败返回-1
void pthread_exit(void* retval);
//用pthread_exit()来调用线程的返回值,用来退出线程,但是退出线程所占用的资源不会随着线程的终止而得到释放
int pthread_join(pthread_t thread, void **retval);
//参数 :thread: 线程标识符,即线程ID,标识唯一线程。retval: 用户定义的指针,用来存储被等待线程的返回值。
//成功返回0,失败返回-1
示例代码
{
#include <stdio.h>
#include <pthread.h>
void *func1(void *arg)
{
static char *p = "t1 is run out";
printf("%ld thread is creat\n",(unsigned long)pthread_self());
printf("param is %d\n",*((int *)arg));
pthread_exit((void *)p);
}
int main()
{
int ret;
pthread_t t1;
int param = 100;
char *pret = NULL;
ret = pthread_create(&t1, NULL,func1, (void *)¶m);
if(ret == 0){
printf("creat t1 success\n");
}
printf("main:%ld\n",(unsigned long)pthread_self());
pthread_join(t1,(void **)&pret);
printf("main: t1 quit:%s\n",pret);
return 0;
}
互斥量
定义:
互斥量从本质上来说像一把锁,在访问共享资源前对互斥量进行加锁,在访问完之后释放互斥量上的锁。对互斥量进行加锁后,任何其他试图再次对互斥量加锁的线程将会被阻塞到当前线程,直到当前线程释放该互斥锁,在设计时需要规定所以所有线程必须遵守相同的数据访问规则。
互斥量作用:
大部分情况,线程使用的数据都是局部变量,变量的地址空间在线程栈空间内,这种情况变量归属单个线程,其他线程无法获得变量。但有的时候,线程间需要共享很多变量,通过数据的共享,完成线程间的交互。如果多个线程并发地共享变量,会出现数据不一致的问题,而互斥量可以使共享资源被唯一访问,能很好地解决这个问题。
1,创建及销毁互斥锁
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t mutex);
//返回:若成功返回0,否则返回错误编号
示例代码:
#include <stdio.h>
#include <pthread.h>
void *func1(void *arg)
{
static char *p = "t1 is run out";
printf("%ld thread is creat\n",(unsigned long)pthread_self());
printf("param is %d\n",*((int *)arg));
pthread_exit((void *)p);
}
int main()
{
int ret;
pthread_t t1;
int param = 100;
char *pret = NULL;
ret = pthread_create(&t1, NULL,func1, (void *)¶m);
if(ret == 0){
printf("creat t1 success\n");
}
printf("main:%ld\n",(unsigned long)pthread_self());
pthread_join(t1,(void **)&pret);
printf("main: t1 quit:%s\n",pret);
return 0;
}
2,加锁及解锁
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex mutex);
int pthread_mutex_trylock(pthread_mutex_t mutex);
int pthread_mutex_unlock(pthread_mutex_t mutex);
//返回:若成功返回0,失败返回错误编码
示例代码:
#include <stdio.h>
#include <pthread.h>
int g_data = 0;
pthread_mutex_t mutex;
void *func1(void *arg)
{
int i;
pthread_mutex_lock(&mutex);
for(i=0;i<5;i++){
printf("t1:%ld thread is creat\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));
sleep(1);
}
pthread_mutex_unlock(&mutex);
}
void *func2(void *arg)
{
printf("t2:%ld thread is creat\n",(unsigned long)pthread_self());
printf("t2:parm is %d\n",*((int *)arg));
}
int main()
{
int ret;
pthread_t t1;
pthread_t t2;
pthread_mutex_init(&mutex, NULL);
int param = 100;
char *pret = NULL;
ret = pthread_create(&t1, NULL,func1, (void *)¶m);
if(ret == 0){
printf("creat t1 success\n");
}
ret = pthread_create(&t2, NULL, func2,(void *)¶m);
if(ret == 0){
printf("creat t2 success\n");
}
printf("main:%ld\n",(unsigned long)pthread_self());
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
3,互斥锁对共享内存的影响
示例代码
#include <stdio.h>
#include <pthread.h>
int g_data = 0;
pthread_mutex_t mutex;
void *func1(void *arg)
{
printf("t1:%ld thread is create\n",(unsigned long)pthread_self());
printf("ti:parm is %d\n",*((int *)arg));
pthread_mutex_lock(&mutex);
while(1){
printf("t1: %d\n",g_data++);
sleep(1);
}
if(g_data == 3){
pthread_mutex_unlock(&mutex);//只有满足条件才能解锁
pthread_exit(NULL);
}
}
void *func2(void *arg)
{
printf("t2:%ld thread is creat\n",(unsigned long)pthread_self());
printf("t2:parm is %d\n",*((int *)arg));
while(1){
printf("t2: %d\n",g_data);
pthread_mutex_lock(&mutex);
g_data++;
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
int main()
{
int ret;
pthread_t t1;
pthread_t t2;
pthread_mutex_init(&mutex, NULL);
int param = 100;
char *pret = NULL;
ret = pthread_create(&t1, NULL,func1, (void *)¶m);
if(ret == 0){
printf("creat t1 success\n");
}
ret = pthread_create(&t2, NULL, func2,(void *)¶m);
if(ret == 0){
printf("creat t2 success\n");
}
printf("main:%ld\n",(unsigned long)pthread_self());
while(1){
printf("main: %d\n",g_data++);
sleep(1);
}
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
测试结果:
可以使用下面的解决方案:互斥量保存在共享内存中,在初始化该锁的时候,设置为进程间共享,这样两个进程连接到共享内存后,都可以获得这个互斥锁,因为已经设置了进程间共享,所以对锁的访问的冲突问题,系统已经解决了。
4,死锁的情况
#include <stdio.h>
#include <pthread.h>
int g_data = 0;
pthread_mutex_t mutex;
pthread_mutex_t mutex2;
void *func1(void *arg)
{
int i;
pthread_mutex_lock(&mutex);
pthread_mutex_lock(&mutex2);
for(i=0;i<5;i++){
printf("t1:%ld thread is creat\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));
sleep(1);
}
pthread_mutex_unlock(&mutex);
}
void *func2(void *arg)
{
pthread_mutex_lock(&mutex2);
pthread_mutex_lock(&mutex);
printf("t2:%ld thread is creat\n",(unsigned long)pthread_self());
printf("t2:parm is %d\n",*((int *)arg));
pthread_mutex_unlock(&mutex2);
}
int main()
{
int ret;
pthread_t t1;
pthread_t t2;
pthread_mutex_init(&mutex, NULL);
int param = 100;
char *pret = NULL;
ret = pthread_create(&t1, NULL,func1, (void *)¶m);
if(ret == 0){
printf("creat t1 success\n");
}
ret = pthread_create(&t2, NULL, func2,(void *)¶m);
if(ret == 0){
printf("creat t2 success\n");
}
printf("main:%ld\n",(unsigned long)pthread_self());
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_mutex_destroy(&mutex);
pthread_mutex_destroy(&mutex2);
return 0;
}
运行结果:
线程条件控制实现线程同步
#include <stdio.h>
#include <pthread.h>
int g_data = 0;
pthread_mutex_t mutex;
pthread_cond_t cond;
void *func1(void *arg)
{
printf("t1:%ld thread is create\n",(unsigned long)pthread_self());
printf("ti:parm is %d\n",*((int *)arg));
static int cnt = 0;
while(1){
pthread_cond_wait(&cond,&mutex);
printf("t1 run\n");
printf("t1: %d\n",g_data);
g_data = 0;
sleep(1);
if(cnt++ == 10){
exit(1);
}
}
}
void *func2(void *arg)
{
printf("t2:%ld thread is creat\n",(unsigned long)pthread_self());
printf("t2:parm is %d\n",*((int *)arg));
while(1){
printf("t2: %d\n",g_data);
pthread_mutex_lock(&mutex);
g_data++;
pthread_mutex_unlock(&mutex);
if(g_data == 3){
pthread_cond_signal(&cond);
}
sleep(1);
}
}
int main()
{
int ret;
pthread_t t1;
pthread_t t2;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond,NULL);
int param = 100;
ret = pthread_create(&t1, NULL,func1, (void *)¶m);
if(ret == 0){
printf("creat t1 success\n");
}
ret = pthread_create(&t2, NULL, func2,(void *)¶m);
if(ret == 0){
printf("creat t2 success\n");
}
printf("main:%ld\n",(unsigned long)pthread_self());
while(1){
printf("main: %d\n",g_data++);
sleep(1);
}
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
运行结果:
本文存在不足会后续补充,仅作为学习记录