线程(thread)
(1)线程就是轻量级的进程;
(2)线程都要依附于进程,进程要是结束了,进程中开辟的所有线程就结束了;
(3)创建一个线程时,只开辟栈区,所以说线程效率高于进程,系统的开销小;
(4)多线程是并发执行的,没有固定的先后顺序,具体执行顺序有操作系统的调度器和线程的调度策略决定。
进程和线程的区别
线程是轻量级的进程,只新建栈区;进程拥有4个区(堆区、栈区、全局区、代码区)
进程之间不能相互访问对方的内存;线程共享全局区,所以可以访问同一个全局区变量
创建线程
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
typedef long pthread_t; //将long型重定义成pthread_t
功能:创建线程
参数:pthread_t *thread 线程的id 参数地址传递方式获取线程id
const pthread_attr_t *attr 设置线程的属性 通常赋值为NULL忽略
void *(*start_routine) (void *) 函数指针 线程执行的函数
void *arg 就是给第三个参数线程执行函数传递参数的
返回值:成功返回 0,失败返回 -1
阻塞等待一个子线程结束
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
功能:阻塞等待子线程结束,回收线程的资源。
参数:pthread_t thread 线程id 阻塞等待的子进程编号
void **retval 用来保存线程结束时的返回值的,通常赋值为NULL
返回值:成功返回 0,失败返回 -1
静态库和共享库
静态库:是以.a结尾的库文件,在编译的时候去静态库找函数远吗,将函数源码编译到程序中,因此体积大,但在运行的时候不需要再加载静态库。
共享库:是以.so结尾的库文件,也叫动态库。在编译的时候去动态库中找函数地址,将函数地址编译到程序中,因此体积小,但是运行的时候需要根据地址去动态库加载函数。
线程的互斥(重点)
什么是互斥(重点)
一个进程可以拥有多个线程,其中每个线程共享该进程的所有资源。但是由于线程共享了进程的资源和地址空间,因此任何线程对系统资源的操作都会给其他线程带来影响。
多线程在访问共享资源时,线程的同步和互斥问题就非常重要了。
互斥:任何时刻一个线程在访问共享资源时,其他线程只能阻塞等待。
解决互斥问题
(1)利用互斥锁来解决
(2)使用信号量来解决
互斥锁使用方法
(1)创建互斥锁 pthread_mutex_t mutex; 全局区
(2)初始化锁 pthread_mutex_init(&mutex,NULL); 主函数
(3)加锁 pthread_mutex_lock(&mutex); 子线程
(4)解锁 pthread_mutex_unlock(&mutex);
线程的同步(重点)
什么是同步
多个线程要按照一定的顺序相互配合完成某个任务。
信号量(semaphore)
信号量使用方法
(1)创建信号量 sem_t sem;
(2)初始化信号量 sem_init(&sem,0,1);
第2个参数是0代表共享
第3个参数是1代表解决互斥问题,是0代表解决同步问题。
(3)请求信号量 sem_wait(&sem); 请求成功,共享资源数-1,请求失败,阻塞等待
(4)释放信号量 sem_post(&sem); 释放信号量,共享资源数+1
功能:信号量初始化
#include "my.h"
typedef struct
{
char name[30];
int age;
}stu_t;
void *fun(void *p)
{
int *q=p;
while(1)
{
printf("age is %d\n",*q);
printf("age is %d\n",*((int*)p));
sleep(1);
}
}
void *func1(void *p)
{
char *q=p;
while(1)
{
printf("name is %s\n",q);
printf("name is %s\n",(char *)p);
sleep(1);
}
}
void* func3(void *p)
{
stu_t *q=p;
while(1)
{
printf("name is %s ,age is %d\n",q->name,q->age);
printf("name is %s ,age is %d\n",((stu_t*)p)->name,((stu_t*)p)->age);
sleep(1);
}
}
int main(int argc, const char *argv[])
{
int age=18;
char name[100]="zhangteng";
stu_t s1;
s1.age=age;
strcpy(s1.name,name);
pthread_t id;
pthread_t id2;
pthread_t id3;
pthread_create(&id,NULL,fun,&age);
pthread_create(&id2,NULL,func1,name);
pthread_create(&id3,NULL,func3,&s1);
getchar();//阻塞等待输入一个字符
return 0;
}
/* demo3.c 字符串 */
#include <stdio.h>
#include <pthread.h>
void *func1(void *arg)
{
static int ret = 10;
static char *p = "t1 is run out";
printf("t1:%ld thread is create\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));
pthread_exit((void *)p);
}
int main()
{
int ret;
int param = 100;
pthread_t t1;
char *pret = NULL;
ret = pthread_create(&t1, NULL, func1, (void *)¶m);
if(ret == 0){
printf("main:create t1 success\n");
}
printf("main: %ld\n",(unsigned long)pthread_self());
// while(1);
pthread_join(t1,(void **)&pret);
printf("main: t1 quit: %s\n",pret);
return 0;
}
/* demo2.c 数据 */
#include <stdio.h>
#include <pthread.h>
void *func1(void *arg)
{
static int ret = 10;
printf("t1:%ld thread is create\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));
pthread_exit((void *)&ret);
}
int main()
{
int ret;
int param = 100;
pthread_t t1;
int *pret = NULL;
ret = pthread_create(&t1, NULL, func1, (void *)¶m);
if(ret == 0){
printf("main:create t1 success\n");
}
printf("main: %ld\n",(unsigned long)pthread_self());
// while(1);
pthread_join(t1,(void **)&pret);
printf("main: t1 quit: %d\n",*pret);
return 0;
}
/* demo1.c */
#include <stdio.h>
#include <pthread.h>
void *func1(void *arg)
{
printf("t1:%ld thread is create\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));
}
int main()
{
int ret;
int param = 100;
pthread_t t1;
ret = pthread_create(&t1, NULL, func1, (void *)¶m);
if(ret == 0){
printf("create t1 success\n");
}
printf("main: %ld\n",(unsigned long)pthread_self());
// while(1);
pthread_join(t1,NULL);
return 0;
}
测试脚本shell
vi test.sh
./a.out ./a.out ./a.out
编辑指令:chmod +x test.sh
运行指令:./test.sh
vi test.cint main() { int i; for(i=0;i<100;i++){ system("./a.out"); } }
2、互斥锁
#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 create\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(&mutex);
printf("t2:%ld thread is create\n",(unsigned long)pthread_self());
printf("t2:param is %d\n",*((int *)arg));
pthread_mutex_unlock(&mutex);
}
void *func3(void *arg)
{
pthread_mutex_lock(&mutex);
printf("t3:%ld thread is create\n",(unsigned long)pthread_self());
printf("t3:param is %d\n",*((int *)arg));
pthread_mutex_unlock(&mutex);
}
int main()
{
int ret;
int param = 100;
pthread_t t1;
pthread_t t2;
pthread_t t3;
pthread_mutex_init(&mutex, NULL);
ret = pthread_create(&t1, NULL, func1, (void *)¶m);
if(ret == 0){
printf("main:create t1 success\n");
}
ret = pthread_create(&t2, NULL, func2, (void *)¶m);
if(ret == 0){
printf("main:create t2 success\n");
}
ret = pthread_create(&t3, NULL, func3, (void *)¶m);
if(ret == 0){
printf("main:create t3 success\n");
}
printf("main: %ld\n",(unsigned long)pthread_self());
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_join(t3,NULL);
pthread_mutex_destroy(&mutex);
return 0;
}