Linux线程

线程包含于进程中,是进程的实际运作单位。一个进程中可包含有多个线程,所有线程共用同一块资源,同样的一个线程的错误会导致整个进程出现问题。使用线程是因为线程的开销远小于进程,同时进程之间数据的通信相对复杂,而线程共用相同空间,会方便很多。
多线程目前在Linux平台上有成熟的pthread库,其主要开发分为三块,线程,互斥锁和条件。
1.线程操作:创建,退出,等待。
API:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
pthread_create:第一个参数为线程的ID,第二个参数是线程的属性(可设置为NULL,默认),第三个参数是线程具体做什么的函数指针,第四个参数是线程需要传的参数(多个参数需要传入用结构体)。
int pthread_exit(void *rval_ptr);
pthread_exit:参数为要返回的数据,要求是static。不然结束之后栈就没了。
int pthread_join(pthread_t thread, void **rval_ptr);
pthread_join:第一个参数为等待哪一个线程,第二个参数是pthread_exit返回的数据存入哪里。

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

void *func1(void *arg)
{
	static char *ret = "it is a test!";
	printf("t1: %ld , thread is created\n", (unsigned long)pthread_self());
	printf("t1:parame get %d\n",*((int *)arg));
	pthread_exit((void *)ret);
}


int main()
{
	pthread_t t1;
	int parame = 55;
	int ret;
	char *pstr = NULL;
	ret = pthread_create(&t1, NULL, func1, (void *)&parame);
	if(ret == 0){
		printf("main :thread create success\n");
	}
	printf("main : thred %ld\n", (unsigned long)pthread_self());
	pthread_join(t1, (void **)&pstr);
	printf("func1 return is : %s\n", pstr);
	return 0;
}

2.互斥锁:创建,加锁,解锁,销毁
互斥量(mutex)就是一把锁,在访问资源前对互斥量加锁,访问结束后解锁。互斥量在使用时需要进行初始化,也可以静态分配为(PTHREAD_MUTEX_INITIALIZER)。
API:
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
pthread_mutex_init:第一个参数为要操作哪一个互斥量,第二个参数为属性,写NULL默认。
int pthread_mutex_lock(pthread_mutex_t *mutex);
pthread_mutex_lock:参数为互斥量地址。
int pthread_mutex_unlock(pthread_mutex_t *mutex);
pthread_mutex_unlock:参数为互斥量地址。
int pthread_mutex_destroy(pthread_mutex_t mutex);
pthread_mutex_destroy:参数为互斥量地址。

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

int data = 0;

pthread_mutex_t mutex1;

void *func1(void *arg)
{
	pthread_mutex_lock(&mutex1);
	printf("t1: %ld , thread is created\n", (unsigned long)pthread_self());
	printf("t1:parame get %d\n",*((int *)arg));
	while(1){
		printf("t1 : %d\n", data++);
		sleep(1);
		if(data == 3){
			printf("3 qiut ///\n");
			pthread_mutex_unlock(&mutex1);
			pthread_exit(NULL);
		}
	}
}


void *func2(void *arg)
{
	printf("t2: %ld , thread is created\n", (unsigned long)pthread_self());
	printf("t2:parame get %d\n",*((int *)arg));
	while(1){
		printf("t2: %d\n", data);	
		pthread_mutex_lock(&mutex1);
		data++;
		pthread_mutex_unlock(&mutex1);
		sleep(1);
	}
}


int main()
{
	pthread_t t1;
	pthread_t t2;
	int parame = 55;
	int ret;
	char *pstr = NULL;
	pthread_mutex_init(&mutex1, NULL);
	ret = pthread_create(&t1, NULL, func1, (void *)&parame);
	if(ret == 0){
		printf("main :thread1 create success\n");
	}
	
	ret = pthread_create(&t2, NULL, func2, (void *)&parame);
	if(ret == 0){
		printf("main :thread2 create success\n");
	}
	
	printf("main : thred %ld\n", (unsigned long)pthread_self());
	while(1){
		printf("main : %d\n", data);
		sleep(1);
	}
	pthread_join(t1, (void **)&pstr);
	pthread_join(t2, (void **)&pstr);
	pthread_mutex_destroy(&mutex1);
	return 0;
}

这个例子定义了一个全局变量data作为共享资源,要实现直到data加到3,线程1才退出。即使一开始是线程2先运行,进入循环,也最多加一次。因为sleep后线程1竞争成功会立即对互斥量加锁,直到data = 3的时候线程解锁并退出。

3.条件操作:创建,销毁,触发,广播,等待
API:
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
pthread_cond_init:第一个参数操作哪一个条件,第二个参数是属性。
int pthread_cond_destroy(pthread_cond_t *cond);
pthread_cond_destroy:参数为条件的地址
int pthread_cond_signal(pthread_cond_t *cond);
pthread_cond_signal:触发哪一个条件。
int pthread_cond_broadcast(pthread_cond_t cond);
pthread_cond_broadcast:触发所有等待这个条件的线程。
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
pthread_cond_wait:第一个参数是条件的地址,第二个参数是互斥锁的地址。

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

int data = 0;
pthread_mutex_t mutex1;
pthread_cond_t cond1;

void *func1(void *arg)
{
	static int cnt = 0;
	while(1){
		pthread_cond_wait(&cond1, &mutex1);
		printf("t1 run ///\n");
		printf("t1 data is :%d\n", data);
		data = 0;
		sleep(1);
		if(cnt ++ == 10){
			printf("return 10\n");
			exit(1);
		}
	}
}

void *func2(void *arg)
{
	while(1){
		
		printf("t2 data is :%d\n", data);
		pthread_mutex_lock(&mutex1);
		data++;
		if(data == 3){
			pthread_cond_signal(&cond1);
		}
		pthread_mutex_unlock(&mutex1);
		sleep(1);
	}
}
//
int main()
{
	
	pthread_t t1;		
	pthread_t t2;		
	int parame = 10;
	int ret;
	pthread_mutex_init(&mutex1, NULL);
	pthread_cond_init(&cond1, NULL);
	ret = pthread_create(&t1, NULL, func1, &parame);
	if(ret == 0){
//		printf("main: thread t1 create success\n");
	}
	
	ret = pthread_create(&t2, NULL, func2, &parame);
	if(ret == 0){
//		printf("main: thread t2 create success\n");
	}
	
	pthread_join(t1, NULL);
	pthread_join(t2, NULL);
	pthread_mutex_destroy(&mutex1);
	pthread_cond_destroy(&cond1);
	return 0;
}

线程的基本操作大致就这些,可以去看一下线程生产者和消费者的相关例子进行学习。
同时也可以看一下这篇文章:

Linux多线程编程初探

上一篇:C++同步锁笔记


下一篇:进程间通信概述