线程:线程可以理解为“轻量级”的进程,它与创建它的进程共享代码段和数据段,同时拥有自己独立的栈。
pthread_create
原型:int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine)(void *),void *arg)
头文件:<pthread.h>,编译时需要链接pthread库
功能:创建新的线程,成功返回0,失败返回错误编号
参数:thread:用来存储新创建的线程id
attr:一个指向pthread_attr_t结构的指针,指向的结构决定了新创建的线程的属性,如优先级等。可为NULL,表示采用默认属性。
start_routine:函数指针。创建线程与创建进程后的执行情况不同。创建进程后,子进程顺着代码执行下去,而创建线程,线程是从一个指定的函数入口开始执行。start_routine指向了线程的函数入口
arg:线程函数入口需要一个参数void *,arg就是该参数,可为NULL
多进程程序中,父进程的退出不会导致子进程的退出;而在多线程程序中,进程结束时,该进程所创建的线程也会结束运行。所以多线程程序中进程需要等待其线程结束才能结束。
pthread_join
原型:int pthread_join(pthread_t thread,void *retval)
头文件:<pthread.h>编译时需要链接pthread库
功能:等待线程结束,成功返回0,失败返回错误编号
参数:thread:要等待结束的线程的id
retval:保存线程结束时的状态,一般为NULL
pthread_exit
原型:void pthread_exit(void *retval)
头文件:<pthread.h>编译时需要链接pthread库
功能:结束线程
参数:retval:线程返回的值,可与pthread_join中的参数retval配合使用,但一般设为NULL
在实际应用中,多个线程往往会访问同一数据或资源,为避免线程之间相互影响,需要引入线程互斥机制,而互斥锁是互斥机制中的一种。
pthread_mutex_init
原型:int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr)
头文件:<pthread.h>
功能:初始化互斥锁,成功返回0,失败返回错误编号
参数:mutex:要初始化的互斥锁的指针
attr:用于设置互斥锁的属性,一般设为NULL,表示默认属性
pthread_mutex_lock
原型:int pthread_mutex_lock(pthread_mutex_t *mutex)
头文件:<pthread.h>
功能:获取互斥锁,成功返回0,失败返回错误编号
参数:mutex:要获取的互斥锁的指针
pthread_mutex_unlock
原型:int pthread_mutex_unlock(pthread_mutex_t *mutex)
头文件:<pthread.h>
功能:释放互斥锁,成功返回0,失败返回错误编号
参数:mutex:要获取的互斥锁的指针
线程互斥
线程互斥:进程创建出两个线程,两个线程互斥
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
pthread_mutex_t mutex;
pthread_t thread[2];
int number=0;
void* work1(void *)
{
int i;
for(i=0;i<10;i++)
{
pthread_mutex_lock(&mutex);
number++;
printf("work1:%d\n",number);
pthread_mutex_unlock(&mutex);
sleep(1);
}
pthread_exit(NULL);
}
void* work2(void *)
{
int i;
for(i=0;i<10;i++)
{
pthread_mutex_lock(&mutex);
number++;
printf("work2:%d\n",number);
pthread_mutex_unlock(&mutex);
sleep(1);
}
pthread_exit(NULL);
}
int main()
{
/*初始化互斥锁*/
pthread_mutex_init(&mutex,NULL);
/*创建线程1*/
pthread_create(&thread[0],NULL,work1,NULL);
/*创建线程2*/
pthread_create(&thread[1],NULL,work2,NULL);
/*等待线程1结束*/
pthread_join(thread[0],NULL);
/*等待线程2结束*/
pthread_join(thread[1],NULL);
return 0;
}
线程同步
多个线程按照规定的顺序执行,即为线程同步。线程同步可利用全局变量来实现,但这会导致执行效率低下,应采用专用的函数来实现同步。
初始化:pthread_cond_t cond_ready=PTHREAD_COND_INITIALIZER;
等待条件成熟:pthread_cond_wait(&cond_ready, &mut);
设置条件成熟:pthread_cond_signal(&cond_ready);
线程同步:进程创建了两个线程,其中线程work2必须在线程work1执行完后才执行
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
pthread_mutex_t mutex;
pthread_t thread[2];
int number=0;
pthread_cond_t cond_ready=PTHREAD_COND_INITIALIZER;
void* work1(void *)
{
while(1)
{
pthread_mutex_lock(&mutex);
number++;
printf("work1:%d\n",number);
pthread_mutex_unlock(&mutex);
if(number==5)
{
pthread_cond_signal(&cond_ready);/*发送信号,说明条件成熟*/
break;
}
sleep(1);
}
pthread_exit(NULL);
}
void* work2(void *)
{
pthread_mutex_lock(&mutex);
if(number<5)
{
pthread_cond_wait(&cond_ready, &mutex);/*需要配合着互斥锁使用,当条件不成熟时会自动释放互斥锁,从而使其它进程能够获取互斥锁*/
}
number=0;
printf("work2:%d\n",number);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
int main()
{
/*初始化互斥锁*/
pthread_mutex_init(&mutex,NULL);
/*创建线程1*/
pthread_create(&thread[0],NULL,work1,NULL);
/*创建线程2*/
pthread_create(&thread[1],NULL,work2,NULL);
/*等待线程1结束*/
pthread_join(thread[0],NULL);
/*等待线程2结束*/
pthread_join(thread[1],NULL);
return 0;
}
生产者消费者
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#define BUFFER_SIZE 8
struct prodcons {
int buffer[BUFFER_SIZE];
pthread_mutex_t lock; //互斥LOCK
int readpos , writepos;
pthread_cond_t notempty; //缓冲区非空条件判断
pthread_cond_t notfull; //缓冲区未满条件判断
};
void init(struct prodcons * b){
pthread_mutex_init(&b->lock,NULL);
pthread_cond_init(&b->notempty,NULL);
pthread_cond_init(&b->notfull,NULL);
b->readpos=0;
b->writepos=0;
}
void put(struct prodcons* b,int data){
pthread_mutex_lock(&b->lock);
if((b->writepos + 1) % BUFFER_SIZE == b->readpos)
{
pthread_cond_wait(&b->notfull, &b->lock) ;
}
b->buffer[b->writepos]=data;
b->writepos++;
if(b->writepos >= BUFFER_SIZE)
b->writepos=0;
pthread_cond_signal(&b->notempty);
pthread_mutex_unlock(&b->lock);
}
int get(struct prodcons *b){
int data;
pthread_mutex_lock(&b->lock);
if(b->writepos == b->readpos)
{
pthread_cond_wait(&b->notempty, &b->lock);
}
data = b->buffer[b->readpos];
b->readpos++;
if(b->readpos >= BUFFER_SIZE)
b->readpos=0;
pthread_cond_signal(&b->notfull);
pthread_mutex_unlock(&b->lock);
return data;
}
#define OVER (-1)
struct prodcons buffer;
void *producer(void *data)
{
int n;
for(n = 0; n < 10000; n++)
{
printf("%d \n", n) ;
put(&buffer, n);
}
put(&buffer, OVER);
return NULL;
}
void *consumer(void * data)
{
int d;
while(1)
{
d = get(&buffer);
if(d == OVER)
break;
printf("%d\n", d);
}
return NULL;
}
int main(void)
{
pthread_t th_a, th_b;
void *retval;
init(&buffer);
pthread_create(&th_a, NULL, producer, 0);
pthread_create(&th_b, NULL, consumer, 0);
pthread_join(th_a, &retval);
pthread_join(th_b, &retval);
return 0;
}