应用程序设计之(5)linux多线程编程

意义:与进程一样为了使多个程序能够并发执行。

定义:进程是资源分配的最小单位线程是程序执行的最小单位(又被称为轻量级进程)。

线程没办法分配空间资源,依附于进程!

线程资源问题

1.一个进程里的所有线程共享一片内存(共享:表示共享内存空间,而不是说内存中的所有数据)

        (1)可共享的内容:

1.静态数据

        (2)私有的内容:

1.线程ID

2.堆.栈

3.程序计数器pc(记录线程运行到什么位置)

线程接口

以下函数的实现属于第三方库函数,所以在编译时需加上-lpthread来链接库函数

头文件#<pthread.h>

pthread create  ( ) 线程创建函数

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
{
thread: 线程ID,需要传递 变量的地址
attr: 设置线程属性参数. 如果选择默认属性则传递NULL
start_routine: 是一个 指针函数的指针 (要求 参数void* 返回值也是void* 的函数)
传递一个线程函数.
arg: 传递给线程函数的参数,如果不需要传参则 为NULL
返回值:
0表示成功
非0 表示错误(返回错误num)
}

pthread——join()等待线程退出函数(并且回收资源)

int pthread_join(pthread_t thread, void **retval);
{
thread: 线程ID
retval: 接收线程退出状态的参数. 不关心状态就为NULL
}

pthread——detach ()线程分离函数(使线程不受其他资源影响)

线程可以分为: 结合属性 与 分离属性 ....
默认线程是结合属性
结合属性: 线程可能会相互之间造成影响(有一定联系)
分离属性: 使线程完全独立执行,相互之间不会造成影响,并且线程可以自动回收资源了
int pthread_detach(pthread_t thread);
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <pthread.h>

pthread_t tid1, tid2;
void *MythreadFun(void *arg)
{
	int n = 5;
	while(n)
	{
		sleep(1);
		printf("thread1-----------\n");
	}
	pthread_exit(NULL);   //与return退出没有区别.
	//return;
}

void *MythreadFun2(void *arg)
{
	int n = 5;
	while(n)
	{
		sleep(1);
		printf("thread2------------\n");
		//sleep(5);
	/*	if(0 != pthread_cancel(tid1))
		{
			perror("cancel");
			break;
		}*/
	}
	pthread_exit("thread2 quit");
}

int main(int argc, char *argv[])
{

	char *quit_msg = NULL;
	pthread_attr_t attr;
	
	if(0 != pthread_attr_init(&attr))
	{
		perror("init");
		return -1;
	}

	if(0 != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
	{
		perror("setdetach");
		return -1;
	}

	if(0 != pthread_create(&tid1, &attr, MythreadFun, NULL))
	{
		perror("create");
		return -1;
	}

	if(0 != pthread_create(&tid2, NULL, MythreadFun2, NULL))
	{
		perror("create2");
		return -1;
	}
	if(0 != pthread_detach(tid2))  //设置分离属性.
	{
		perror("detach");
		return -1;
	}
/*
	if(0 != pthread_join(tid1, NULL))
	{
		perror("join");
		return -1;
	}
*/
	while(1)
	{
		sleep(1);
		printf("mainThread---------\n");
	}
	return 0;
}

pthread_self () 获取指定线程 

pthread_t pthread_self(void);
{
返回线程id
}

pthread_cancel 结束指定线程

int pthread_cancel(pthread_t thread);
{
结束指定线程. 但是不能指定分离属性的线程
}

pthread_exit 线程退出函数(相当于普通函数return)

void pthread_exit(void *retval);
{
reatval: 设置线程退出状态.
}

 线程的同步和互斥

1.同步

使得线程之间按照某一种顺序来执行,这就是同步的概念

实现方式:

1.信号量

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <pthread.h>

int flag = 0;
int m  = 1;

void *MythreadFun(void *arg)
{
	int n = 1;
	while(n)
	{
		if(flag == 0)
		{
			printf("thread1-----------\n");
			m++;
			flag = 1;
		}
		usleep(50000);
	}
	pthread_exit(NULL);   //与return退出没有区别.
}

void *MythreadFun2(void *arg)
{
	int n = 1;
	while(n)
	{
		if(flag == 1)
		{
			printf("thread2****%d\n", m);	
			flag = 0;
		}
		usleep(50000);
	}
	pthread_exit("thread2 quit");
}

int main(int argc, char *argv[])
{
	pthread_t tid1, tid2;
	char *quit_msg = NULL;

	if(0 != pthread_create(&tid1, NULL, MythreadFun, NULL))
	{
		perror("create");
		return -1;
	}

	if(0 != pthread_create(&tid2, NULL, MythreadFun2, NULL))
	{
		perror("create2");
		return -1;
	}

	if(0 != pthread_join(tid1, NULL)) //阻塞函数,等待指定线程退出.
	{
		perror("join");
		return -1;
	}
	pthread_join(tid2, (void**)&quit_msg);

	printf("%s\n", quit_msg);

	while(1)
	{
		sleep(1);
		printf("mainThread---------\n");
	}
	return 0;
}

2.条件变量

2.互斥

对临界资源的一种保护措施,在线程访问该资源的时候其他线程不能访问

实现方式:

1.互斥锁

其实信号量与条件变量也能实现互斥

注意:互斥锁不能直接用于锁程序代码,只能锁临界资源

互斥锁接口:
{
初始化锁:int pthread_mutex_init(pthread_mutex_t *mutex, const
pthread_mutexattr_t *mutexattr);
{
mutex: 锁变量的地址
mutexattr: 为NULL使用默认属性
}
加锁:
解锁:
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <pthread.h>

int m1=0;
int m2=0;
pthread_mutex_t mutex;

void *MythreadFun(void *arg)
{
	while(1)
	{
		pthread_mutex_lock(&mutex);
		++m1;
		++m2;
		pthread_mutex_unlock(&mutex);
		//usleep(5000);
	}
	pthread_exit(NULL);   //与return退出没有区别.
}

void *MythreadFun2(void *arg)
{
	while(1)
	{
		pthread_mutex_lock(&mutex);
		if(m1 == m2)
		{
			printf("相等---\n");
		}
		else
		{
			printf("不相等--- #%d\n", m1-m2);
		}
		//usleep(5000);
		pthread_mutex_unlock(&mutex);
	}
	pthread_exit("thread2 quit");
}

int main(int argc, char *argv[])
{
	pthread_t tid1, tid2;
	char *quit_msg = NULL;

	pthread_mutex_init(&mutex, NULL);

	if(0 != pthread_create(&tid1, NULL, MythreadFun, NULL))
	{
		perror("create");
		return -1;
	}

	if(0 != pthread_create(&tid2, NULL, MythreadFun2, NULL))
	{
		perror("create2");
		return -1;
	}

	if(0 != pthread_join(tid1, NULL)) //阻塞函数,等待指定线程退出.
	{
		perror("join");
		return -1;
	}
	pthread_join(tid2, (void**)&quit_msg);

	printf("%s\n", quit_msg);

	while(1)
	{
		sleep(1);
		printf("mainThread---------\n");
	}
	return 0;
}

练习题:

利用信号量实现线程同步. 例子: 创建两个线程,一个全局变量n=0,要求一个线程对n++, 另外一个线程打印n,要求输出结果必须是0,1,2,3,4,5,6...这个顺序

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
int n=0;
sem_t sem_g,sem_p;
void *myfun1(void *arg)
{
    while(1)
    {
        sem_wait(&sem_g);
        usleep(50000);
        n++;
        sem_post(&sem_p);
    }
    pthread_exit(NULL);
}

void *myfun2(void *arg)
{
    while(1)
    {
        sem_wait(&sem_p);
        usleep(50000);
        printf("***%d*****\n",n);
        sem_post(&sem_g);
    }
    pthread_exit(NULL);
    
}
int main(int argc, char *argv[])
{ 
    sem_init(&sem_g,0,1);
    sem_init(&sem_p,0,2);
    pthread_t tid1,tid2;

    if(0!=pthread_create(&tid1,NULL,myfun1,NULL))
    {
        perror("pthread_create");
        return -1;
    }
    if(0!=pthread_create(&tid1,NULL,myfun2,NULL))
    {
        perror("pthread_create");
        return -1;
    }
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    sem_destroy(&sem_g);
    sem_destroy(&sem_p);
    return 0;
} 

运行

结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞赴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值