首页 > 编程知识 正文

多线程定时任务并发执行(所有线程等待事件linux,linux多线程机制线程同步)

时间:2023-05-04 22:16:14 阅读:123829 作者:1817

1 .引言

目前,许多常见的多任务操作系统都提供线程机制,线程是程序中的

单一顺序控制流程。 利用多线程进行编程是指分为执行一个程序(进程)任务的多个部分(线程)

中选择所需的墙类型。 每个线程是一个序列的单个控制流,所有线程都是同时执行的。 这样,多线程程序就可以实现并行计算,有效利用多处理器。 线程分为用户级线程和内核级线程

课程有两种基本类型。 用户级线程不需要内核支持,可以通过用户程序实现。 线程调度、同步和互斥必须由用户程序自己完成。 内核级线程需要内核参与,内核完成生产线

程序调度并提供相应的系统调用,以便用户程序可以使用这些接口函数来控制和管理线程。 Linux操作系统提供了一个LinuxThreads库,并与之兼容

POSIX1003.1c标准内核级多线程函数库。 linuxthreads库提供了多线程编程的几个重要函数,多线程编程包括

pthread.h文件。

2.LinuxThread的键库函数

2.1创建和退出线程

int pthread _ create (pthread _ t * pthread,const pthread_attr_t

*attr,void * (start _ routine (void ) )、void

*arg; 调用此函数将创建新线程,并在创建后执行start_routine

指定的程序。 其中attr参数是用户创建线程的属性,NULL表示使用默认属性创建线程。 arg到start_routine

传递的参数。 成功创建新线程后,系统会自动为新线程分配线程ID号,并通过pthread返回调用方。

void pthread _ exit (void * value _ ptr ); 调用此函数时,线程将终止。 参数value_ptr是指向返回值的指针。

2.2线程控制函数

phread_self(void ); 为了区分线程,创建线程时系统可以分配唯一的ID号,pthread_create (返回给调用方,或从pthread_self )获取自己的线程ID。

int pthread _ join (pthread-t thread,void * *status ); 此函数的作用是等待线程结束。 调用pthread_join ()的线程将挂起,直到线程ID由参数thread指定的线程结束。

int pthread _ detach (pthread _ t pthread ); 当参数pthread表示的线程结束时,它将立即释放该线程占用的所有资源。

2.3线程之间的独占

独占量与关键节类似,只有具有独占量的线程才能访问资源。

因为只有一个互斥对象,所以在任何情况下都决定共享资源(代码或变量)不会同时被多个线程访问。 使用互斥锁,不仅可以确保同一APP应用程序的不同线程上的资源安全

完全共享,可以在不同APP应用程序的线程之间安全地共享资源。 在Linux上,通过在pthread_mutex_t中定义互斥体机制来完成互斥操作。 具体的

操作函数如下

pthread _ mutex _ init (pthread _ mutex _ t * mutex,const

pthread_mutexattr_t

*attr; 初始化互斥体变量mutex。 参数attr表示将根据attr属性创建互斥体变量mutex。 如果参数attr为NULL,则为默认参数

创建公式。

pthread _ mutex _ lock (pthread _ mutex _ t * mutex ); 锁定互斥变量。 如果由mutex指定的互斥变量被锁定,则调用线程将被阻止,直到具有mutex的线程解锁mutex。

pthread _ mutex _ unlock (pthread _ mutex _ t * mutex ); 解除参数mutex指定的互斥体变量的锁定。

2.4线程之间的同步

同步是线程等待某个事件的发生,当等待的事件发生时,等待的线程继续与事件一起执行。 如果等待的活动没有到达,它将挂起。 在linux操作系统中,条件变量是同步的。

pthread _ cond _ init (pthread _ cond _ t * cond,const pthread_cond_t *attr ); 此函数根据参数attr中指定的属性初始化条件变量cond。

pthread _ cond _ wait (pthread _ cond _ t * cond,pthread_mutex_t *mutex ); 等待一个事件(条件变量)的发生,发出调用的线程将自动阻止,直到相应的条件变量设置为1。 等待状态线程不消耗CPU时间。

pthread _ cond _ signal (pthread _ cond _ t * cond ); 取消阻止等待由参数cond指定的条件变量的线程的状态。

3 .多线程编程应用实例

这里利用多线程技术实现生产者和消费者的问题,生产者线程将数据写入缓冲区

消费者线程从缓冲器读取数据,为了生产者线

程和消费者线程共享同一缓冲区,为了正确读写数据,在使用缓冲队列时必须保持互斥。生产者线程和消费者线程必

须满足:生产者写入缓冲区的数目不能超过缓冲区容量,消费者读取的数目不能超过生产者写入的数目。在程序中使用了一个小技巧来判断缓冲区是空还是满。在初

始化时读指针和写指针为0;如果读指针等于写指针,则缓冲区是空的;如果(写指针+ 1) % N

等于读指针,则缓冲区是满的,%表示取余数,这时实际上有一个单元空出未用。下面是完整的程序段和注释。

#include

#include

#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("%dn", d);

}

return NULL;

}

int main(void)

{

pthread_t th_a, th_b;

void *retval;

init(&buffer);

pthread_create(&th_a, NULL, producer, 0);

& nbsp;   pthread_create(&th_b, NULL, consumer, 0);

pthread_join(th_a, &retval);

pthread_join(th_b, &retval);

return 0;

}

面的例子中,生产者负责将1到1000的整数写入缓冲区,而消费者负责从同一个缓冲区中读取写入的整数并打印出来。因为生产者和消费者是两个同时运行的线

程,并且要使用同一个缓冲区进行数据交换,因此必须利用一种机制进行同步。通过上面的例子我们可以看到,多线程的最大好处是,除堆栈之外,几乎所有的数据

均是共享的,因此线程间的通讯效率很高;缺点:因为共享所有数据,从而非常容易导致线程之间互相破坏数据,这一点在编程时必须注意。

4.结束语

Linux中基于POSIX标准的很好的支持了多线程技术,它减少了程序并发执行时的系统开销,提高了计算机的工作效率。在具体编程过程中要了

解线程的间的关系,还要考虑共享数据的保护,在互斥和同步机制下保证代码的高效运行,程序编译时用gcc -D –REENTRANT

-libpthread.xx.so filename.c编译。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。