Linux 多线程-小白

pthread_create函数
创建一个新线程,并行的执行任务。
#include <pthread.h>
	int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
	返回值:成功:0;	失败:错误号。
参数:	
	pthread_t:当前Linux中可理解为:typedef  unsigned long int  pthread_t;
参数1:传出参数,保存系统为我们分配好的线程ID
	参数2:通常传NULL,表示使用线程默认属性。若想使用具体属性也可以修改该参数。
	参数3:函数指针,指向线程主函数(线程体),该函数运行结束,则线程结束。
	参数4:线程主函数执行期间所使用的参数。
在一个线程中调用pthread_create()创建新的线程后,当前线程从pthread_create()
返回继续往下执行,而新的线程所执行的代码由我们传给pthread_create的函数指针start_routine决定。
start_routine函数接收一个参数,
是通过pthread_create的arg参数传递给它的,该参数的类型为void *,
这个指针按什么类型解释由调用者自己定义。
start_routine的返回值类型也是void *,
这个指针的含义同样由调用者自己定义。
start_routine返回时,这个线程就退出了,
其它线程可以调用pthread_join得到start_routine的返回值,

pthread_create成功返回后,新创建的线程的id被填写到
thread参数所指向的内存单元。
attr参数表示线程属性,

互斥锁
 typedef struct ct_sum
    {
    
     int sum;
      pthread_mutex_t lock;
    }ct_sum;
 pthread_mutex_lock(&(((ct_sum*)cnt)->lock));
---------共享数据文件及操作---------
 pthread_mutex_unlock(&(((ct_sum*)cnt)->lock));
 pthread_exit(NULL);
#include <pthread.h>//线程头文件
#include <stdio.h>
#include <stdlib.h>

int my_global;//全局变量

void* my_thread_handle(void *arg) //线程执行的函数
{
    
    
	int val;

	val = *((int*)arg);

	printf("new thread begin, arg=%d\n", val);
	my_global += val;

	sleep(3);

	pthread_exit(&my_global);//线程结束

	//  不再执行
	printf("new thread end\n");
}
//gcc  m.c    -o   auto.exe -D_REENTRANT  -lpthread //加这个宏保证数据的安全相当于互斥锁(不常用)
int main(void)//创建线程gcc m.c -pthread -o auto.exe  编译需指定pthread这个库
{
    
    
	pthread_t  mythread;//线程句柄
	int arg;
	int ret;
	void *thread_return;//保存指定的线程返回的参数

	arg = 100;
	my_global = 1000;

	printf("my_global=%d\n", my_global);
	printf("ready create thread...\n");
	
	ret = pthread_create(&mythread, 0, my_thread_handle, &arg);//创建线程
	if (ret != 0) {
    
    
		printf("create thread failed!\n");
		exit(1);
	}

	printf("wait thread finished...\n");
	ret = pthread_join(mythread, &thread_return);//等待指定的线程结束
	if (ret != 0) {
    
    
		printf("pthread_join failed!\n");
		exit(1);
	}
	printf("wait thread end, return value is %d\n", *((int*)thread_return));
	printf("my_global=%d\n", my_global);

	printf("create thread finished!\n");
}

如果要求最多只允许一个线程进入临界区,则使用互斥量
如果要求多个线程之间的执行顺序满足某个约束,则使用信号量

信号量

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

#define BUFF_SIZE 80

char buff[BUFF_SIZE];
sem_t sem;//信号量一定要定义为全局

static void* str_thread_handle(void *arg) //线程函数
{
    
    
	while(1) {
    
    
		//P(sem)p操作是指判读信号量是否可以开始执行,如果可以执行就执行并将信号量更改
		if (sem_wait(&sem) != 0) //信号量p操作第一执行的时候会阻塞在这里,v操作之后信号量为1开始执行
		{
    
    
			printf("sem_wait failed!\n");
			exit(1);
		}
		
		printf("string is: %slen=%d\n", buff, strlen(buff));
		if (strncmp(buff, "end", 3) == 0) {
    
    
			break;
		}
	}
}

int main(void)
{
    
    
	int ret;
	pthread_t  str_thread;//线程句柄
	void *thread_return;//保存指定的线程返回的参数

	ret = sem_init(&sem, 0, 0);//初始化信号量
	if (ret != 0)
	 {
    
    
		printf("sem_init failed!\n");
		exit(1);
	}

	ret = pthread_create(&str_thread, 0, str_thread_handle, 0);//创建线程
	if (ret != 0) {
    
    
		printf("pthread_create failed!\n");
		exit(1);
	}

	while (1) {
    
    
		fgets(buff, sizeof(buff), stdin);//等待用户输入字符串

		//V(sem)//信号量v操作 主线程先执行这个函数 执行了v操作p操作激活子线程开始执行
		if (sem_post(&sem) != 0) 
		{
    
    
			printf("sem_post failed!\n");
			exit(1);
		}
		
		if (strncmp(buff, "end", 3) == 0) {
    
    
			break;
		}
	}

	ret = pthread_join(str_thread, &thread_return);//等待指定线程结束
	if (ret != 0) {
    
    
		printf("pthread_join failed!\n");
		exit(1);
	}

	ret = sem_destroy(&sem);//删除信号量
	if (ret != 0) {
    
    
		printf("sem_destroy failed!\n");
		exit(1);
	}

	return 0;
}

互斥量

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

#define BUFF_SIZE 80

int global_value = 1000;
pthread_mutex_t  lock;//互斥锁

static void* str_thread_handle(void *arg) 
{
    
    
	int i = 0;

	for (i=0; i<10; i++) {
    
    
		pthread_mutex_lock(&lock);//上锁

		if (global_value  > 0) {
    
    
			// work
			sleep(1);
			printf("soled ticket(%d) to ChildStation(%d)\n",
				global_value, i+1);
		}
		global_value--;
		
		pthread_mutex_unlock(&lock);//解锁
		sleep(1);
	}
}

int main(void)
{
    
    
	int ret;
	pthread_t  str_thread;//线程句柄
	void *thread_return;//线程返回值
	int i;

	

	ret = pthread_mutex_init(&lock, 0);//初始化互斥锁
	if (ret != 0) {
    
    
		printf("pthread_mutex_init failed!\n");
		exit(1);
	}

	ret = pthread_create(&str_thread, 0, str_thread_handle, 0);//创建线程
	if (ret != 0) {
    
    
		printf("pthread_create failed!\n");
		exit(1);
	}

	for (i=0; i<10; i++) {
    
    
		pthread_mutex_lock(&lock);//上互斥锁
		
		if (global_value  > 0) {
    
    
			// work
			sleep(1);
			printf("soled ticket(%d) to MainStation(%d)\n",
				global_value, i+1);
		}
		global_value--;
		
		
		pthread_mutex_unlock(&lock);//解互斥锁
		sleep(1);
	}

	ret = pthread_join(str_thread, &thread_return);//等待指定线程结束
	if (ret != 0) {
    
    
		printf("pthread_join failed!\n");
		exit(1);
	}

	ret = pthread_mutex_destroy(&lock);//释放互斥锁
	if (ret != 0) {
    
    
		printf("pthread_mutex_destroy failed!\n");
		exit(1);
	}

	return 0;
}

条件变量 多线程必备 (用于线程等待信号,当信号发生时线程开始执行 配合互斥锁使用)

#include <stdio.h>
#include <pthread.h>

pthread_mutex_t mutex;//互斥锁
pthread_cond_t cond;//条件变量

void *thread1(void *arg)//线程一执行的函数
{
    
    

	
	while (1) {
    
    

		printf("thread1 is running\n");
		pthread_mutex_lock(&mutex);//上互斥锁
		
		//等待条件变量的信号。这个里面会进行解锁,被唤醒时会进行加锁
		pthread_cond_wait(&cond, &mutex);
		
		
		printf("thread1 applied the condition\n");
		pthread_mutex_unlock(&mutex);//解互斥锁

		sleep(4);
	}

}


void *thread2(void *arg)//线程二执行的函数
{
    
    
	while (1) {
    
    

		printf("thread2 is running\n");
		pthread_mutex_lock(&mutex);//上互斥锁
		
		//等待条件变量的信号。这个里面会进行解锁,被唤醒时会进行加锁
		pthread_cond_wait(&cond, &mutex);//等待条件变量的信号
		
		
		
		
		printf("thread2 applied the condition\n");
		pthread_mutex_unlock(&mutex);//解互斥锁

		sleep(2);

	}

}

int main()
{
    
    

	pthread_t thid1, thid2;

	printf("condition variable study!\n");

	pthread_mutex_init(&mutex, NULL);//初始化互斥锁

	pthread_cond_init(&cond, NULL);//初始化条件变量

	pthread_create(&thid1, NULL, (void *)thread1, NULL);//创建线程1

	pthread_create(&thid2, NULL, (void *)thread2, NULL);//创建线程2

	do {
    
    

		pthread_cond_signal(&cond);//唤醒某一个等待该条件变量的线程 随机
        sleep(1);

	} while (1);

	

	return 0;

}
/**************************************************************************************
1.条件变量初始化  
    pthread_cond_init
    原型:int pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr);
参数:cond,  条件变量指针
      attr    条件变量高级属性
man 安装:   apt-get install manpages-posix-dev


2.唤醒一个等待线程
    pthread_cond_signal 通知条件变量,唤醒一个等待者 
原型: int pthread_cond_signal (pthread_cond_t *cond);
参数:cond,  条件变量指针

      
3.唤醒所有等待该条件变量的线程
pthread_cond_broadcast  广播条件变量 
原型: int pthread_cond_broadcast (pthread_cond_t *cond);
参数:cond,  条件变量指针


4.等待条件变量/超时被唤醒
pthread_cond_timedwait  等待条件变量cond被唤醒,直到由一个信号或广播,或绝对时间abstime到 * 
才唤醒该线程
原型: int pthread_cond_timedwait(
pthread_cond_t *cond,
pthread_mutex_t *mutex,
const struct timespec *abstime);
参数:cond,  条件变量指针
      pthread_mutex_t *mutex 互斥量
      const struct timespec *abstime 等待被唤醒的绝对超时时间
      

5.等待条件变量被唤醒
pthread_cond_wait  等待条件变量cond被唤醒(由一个信号或者广播) 
原型: int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex);
参数:cond,  条件变量指针
      pthread_mutex_t *mutex 互斥量
常见错误码:  [EINVAL] cond或mutex无效,
             [EINVAL] 同时等待不同的互斥量  
             [EINVAL] 主调线程没有占有互斥量  


6. 释放/销毁条件变量
pthread_cond_destroy  待销毁的条件变量 
原型: int pthread_cond_destroy (pthread_cond_t *cond);
参数:cond,  条件变量指针
****************************************************************************************/

猜你喜欢

转载自blog.csdn.net/qq_45743563/article/details/109581092