您的位置:首页 > 其它

跨平台线程库——pThread

2016-05-03 17:05 337 查看
基本接口介绍:

1. pthread_create



#include <pthread.h>

int pthread_create(pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg);

创建一个由调用线程控制的新的线程并发运行。新的线程使用start_routine作为实现体,并以arg作为第一个参数。

新的线程可以通过调用pthread_exit显式结束,或者通过start_routine return来隐式结束。其中后者等价于调用pthread_exit并以start_routine 的返回值作为退出码。

新线程的初始信号状态继承自他的创建线程,并且没有挂起的信号。pthread-win32暂时未实现信号量。

attr参数指明新线程的属性,如果attr=NULL,则使用默认属性:新线程是joinable(not detached),和默认的调度策略(非实时)

返回值:如果成功,新线程的指针会被存储到thread的参数中,并返回0。如果错误则一个非0的错误码返回。

如果返回EAGAIN,没有足够的系统资源创建一个线程,或者已经存在大于PTHREAD_THREADS_MAX个活跃线程。

2. pthread_exit

#include <pthread.h>


void pthread_exit(void *retval);

pthread_exit结束调用线程的执行.所有通过pthread_cleanup_push设置的清除句柄将会被反序执行(后进先出)。

所以key值非空的线程特定数据Finalization functions被调用(参见pthread_key_create)。

最后调用线程被终止。

retval是这个线程结束的返回值,可以通过在别的线程中调用pthread_join来获取这个值。

没有返回值。

3. pthread_join

#include <pthread.h>

int pthread_join(pthread_t th, void **thread_return);



挂载一个在执行的线程直到该线程通过调用pthread_exit或者cancelled结束。(阻塞的方式等待指定的现成结束,释放线程资源)

如果thread_return不为空,则线程th的返回值会保存到thread_return所指的区域。

th的返回值是它给pthread_exit的参数,或者是pthread_canceled 如果是被cancelled的。

被依附的线程th必须是joinable状态。一定不能是detached通过使用pthread_detach或者pthread_create中使用pthread_create_detached属性。

当一个joinable线程结束时,他的资源(线程描述符和堆栈)不会被释放直到另一个线程对它执行pthread_join操作。

如果成功,返回值存储在thread_return中,并返回0,否则返回错误码:

ESRCH:找不到指定线程

EINVAL:线程th是detached或者已经存在另一个线程在等待线程th结束

EDEADLK:th的参数引用它自己(即线程不能join自身)

4.pthread_cancel

#include <pthread.h>

int pthread_cancel(pthread_t thread);

int pthread_setcancelstate(int state, int *oldstate);

int pthread_setcanceltype(int type, int *oldtype);

void pthread_testcancel(void);

Cancellation是一种一个线程可以结束另一个线程执行的机制。更确切的说,一个线程可以发生Cancellation请求给另一个线程。

根据线程的设置,收到请求的线程可以忽视这个请求,立即执行这个请求或者延迟到一个cancellation点执行。

当一个线程执行Cancellation请求,相当于在那个点执行pthread_exit操作退出:所有cleanup句柄被反向调用,所有析构函数被调用结束线程并返回pthread_canceled.

5.pthread_cond

#include <pthread.h>


pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);

int pthread_cond_signal(pthread_cond_t *cond);

int pthread_cond_broadcast(pthread_cond_t *cond);

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);

int pthread_cond_destroy(pthread_cond_t *cond);

pthread_cond_init初始化条件变量,通过cond_attr,如果cond_attr是null则使用默认属性。也可以通过常量PTHREAD_COND_INITIALIZER静态初始化。

pthread_cond_signal激活一个正在等待条件变量cond的线程。如果没有线程在等待则什么也不会发生,如果有多个线程在等待,则只能激活一个线程,带未指定是哪个线程(根据操作系统自己的调度策略选择)。

pthread_cond_broadcast激活所有在等待条件变量cond的线程。

pthread_cond_wait自动解锁mutex(pthread_unlock_mutex)等待条件变量cond发送。线程的执行被挂起不消耗cpu时间直到cond发送。在wait的入口mutex必须被锁住。

在重新回到线程前,pthread_cond_wait会重新获得mutex(pthread_lock_mutex).解锁mutex和挂起是自动进行的。因此,如果所有线程在发送cond前都申请mutex的话,

这种wait的内部实现机制能够保证在线程锁住mutex和线程wait之间不会有cond发送操作发送。

pthread_cond_timedwaitpthread_cond_wait,只是多了个超时设置,如果超时,则重新获取mutex并且返回ETIMEDOUT,时间为绝对时间。

pthread_cond_destroy销毁一个条件变量。必须没有线程在wait该条件变量。

condition函数是异步信号不安全的,容易产生死锁,必须自己控制调用流程避免死锁。

6.semaphore



#include <semaphore.h>

int sem_init(sem_t *sem, int pshared, unsigned int value);

int sem_wait(sem_t * sem);

int sem_timedwait(sem_t * sem, const struct timespec *abstime);

int sem_trywait(sem_t * sem);

int sem_post(sem_t * sem);

int sem_post_multiple(sem_t * sem, int number);

int sem_getvalue(sem_t * sem, int * sval);

int sem_destroy(sem_t * sem);

sem_init:
初始化信号量,pshared表示该信号量是否只属于当前进程(pshared==0),如果pshared不为0则表示可以在进程间共享。value表示该信号量的初始值。

sem_wait:如果信号量的值大于0,则自动减1并立即返回。否则线程挂起直到sem_post或sem_post_multiple增加信号量的值。

sem_timedwait:同sem_wait,只是多了个超时设置,如果超时,首先将全局变量errno设为ETIMEDOUT,然后返回-1.

sem_trywait:如果信号量的值大于0,将信号量减1并立即返回,否则将全局变量errno设为ETIMEDOUT,然后返回-1。sem_trywait不会阻塞。

sem_post:释放一个正在等待该信号量的线程,或者将该信号量+1.

sem_post_multiple:释放多个正在等待的线程。如果当前等待的线程数n小于number,则释放n个线程,并且该信号量的值增加(number - n).

sem_get_value:返回信号量的值。在pthread-win32实现中,正值表示当前信号量的值,负值的绝对值表示当前正在等待该信号量的线程数。虽然在POSIX不需要这么表示,但是也是同样含义。

信号量(sem)与条件变量(cond)的主要差别在于,条件变量等待必须在发送之前,否则容易出现死锁,而信号量等待可以在发送之后执行。一句话概括信号量对于操作的时序没有要求。

几个测试程序:

1.

#include <QCoreApplication>
#include <iostream>
#include "pthread.h"

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void *Func1(void *);
void *Func2(void *);

int i = 1;

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

#ifdef WIN32
#ifdef PTW32_STATIC_LIB
pthread_win32_process_attach_np();
pthread_win32_thread_attach_np();
#endif
#endif

pthread_t thread1;
pthread_t thread2;

pthread_create(&thread1,NULL,Func1,(void*)NULL);
pthread_create(&thread2,NULL,Func2,(void*)NULL);
pthread_join(thread2,NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);

#ifdef WIN32
#ifdef PTW32_STATIC_LIB
pthread_win32_process_detach_np();
pthread_win32_thread_detach_np();
#endif
#endif

system("Pause");

return a.exec();
}

void *Func1(void *junk)
{
for(i = 1;i <= 9;i++)
{
if(i%3==0)
{
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}

else
{
std::cout << "thread1: " << i << std::endl;
}
}
return NULL;
}

void *Func2(void *junk)
{
while(i<9)
{
if(i%3!=0)
{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
pthread_mutex_unlock(&mutex);
}
else
{
std::cout << "thread2: " << i << std::endl;
}
}
return NULL;
}




2.

#include <stdio.h>
#include <Windows.h>
#include "pthread.h"
#include <ctype.h>

typedef struct arg_set
{
char *fname;
int count;
int tid;
}ARG_SET;

bool bWait = false;
ARG_SET *mailbox = NULL;
pthread_mutex_t read_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t write_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t read_cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t write_cond = PTHREAD_COND_INITIALIZER;

void main(int ac, char *av[])
{
pthread_win32_process_attach_np();
pthread_win32_thread_attach_np();

pthread_t t1, t2, t3;
ARG_SET args1, args2, args3;
void *count_words(void *);
int reports_in = 0;
int total_words = 0;

if (4 != ac)
{
printf("usage: %s file1 file2 file3\n", av[0]);
return;
}

args1.fname = av[1];
args1.count = 0;
args1.tid = 1;
pthread_create(&t1, NULL, count_words, (void *)&args1);

args2.fname = av[2];
args2.count = 0;
args2.tid = 2;
pthread_create(&t2, NULL, count_words, (void *)&args2);

args3.fname = av[3];
args3.count = 0;
args3.tid = 3;
pthread_create(&t3, NULL, count_words, (void *)&args3);

while(reports_in < 3)
{
printf("MAIN: waiting for flag to go up\n");
pthread_mutex_lock(&read_lock);
bWait = true;
pthread_cond_wait(&read_cond, &read_lock);
bWait = false;
pthread_mutex_unlock(&read_lock);
printf("MAIN: wow! flag was raised, I have the lock\n");

printf("MAIN: %7d: %s\n", mailbox->count, mailbox->fname);
total_words += mailbox->count;

Sleep(10);

printf("MAIN: Ok, I've read the thread %d mail\n", mailbox->tid);

pthread_mutex_lock(&write_lock);
pthread_cond_signal(&write_cond);
pthread_mutex_unlock(&write_lock);
printf("MAIN: raising write flag\n");

reports_in++;
}
printf("%7d: total words\n", total_words);

pthread_mutex_destroy(&read_lock);
pthread_mutex_destroy(&write_lock);
pthread_cond_destroy(&read_cond);
pthread_cond_destroy(&write_cond);

pthread_win32_thread_detach_np();
pthread_win32_process_detach_np();

system("pause");
}

void *count_words(void *a)
{
ARG_SET *args = (ARG_SET*)a;
FILE *fp;
int c, prevc = '\0';

if (NULL != (fp = fopen(args->fname, "r")))
{
while((c = getc(fp)) != EOF)
{
if (!isalnum(c) && isalnum(prevc))
{
args->count++;
}
prevc = c;
}
fclose(fp);
}
else
{
perror(args->fname);
}

printf("COUNT %d: waiting to get lock\n", args->tid);

pthread_mutex_lock(&write_lock);
if (NULL != mailbox)
{
printf("COUNT %d: oops..mailbox not empty. wait for signal\n", args->tid);
pthread_cond_wait(&write_cond, &write_lock);
}

printf("COUNT %d: OK, I can write mail\n", args->tid);
mailbox = args;

while (!bWait)
{
Sleep(1);
}
pthread_mutex_lock(&read_lock);
pthread_cond_signal(&read_cond);    /* raise the flag */
pthread_mutex_unlock(&read_lock);

printf("COUNT %d: raising read flag\n", args->tid);

pthread_mutex_unlock(&write_lock);    /* release the mailbox */
printf("COUNT %d: unlocking box\n", args->tid);

return NULL;
}


3.

#include <stdio.h>
#include <Windows.h>
#include "pthread.h"
#include "semaphore.h"
#include <ctype.h>

typedef struct arg_set
{
char *fname;
int count;
int tid;
}ARG_SET;

ARG_SET *mailbox = NULL;
static sem_t sem_write;
static sem_t sem_read;

void main(int ac, char *av[])
{
pthread_win32_process_attach_np();
pthread_win32_thread_attach_np();

pthread_t t1, t2, t3;
ARG_SET args1, args2, args3;
void *count_words(void *);
int reports_in = 0;
int total_words = 0;

if (4 != ac)
{
printf("usage: %s file1 file2 file3\n", av[0]);
return;
}

if (-1 == sem_init(&sem_read, 0 , 1)
|| -1 == sem_init(&sem_write, 0, 0))
{
return;
}

args1.fname = av[1];
args1.count = 0;
args1.tid = 1;
pthread_create(&t1, NULL, count_words, (void *) &args1);

args2.fname = av[2];
args2.count = 0;
args2.tid = 2;
pthread_create(&t2, NULL, count_words, (void *) &args2);

args3.fname = av[3];
args3.count = 0;
args3.tid = 3;
pthread_create(&t3, NULL, count_words, (void *) &args3);

while(reports_in < 3)
{
printf("MAIN: waiting for sub thread write\n");
sem_wait(&sem_write);

printf("MAIN: %7d: %s\n", mailbox->count, mailbox->fname);
total_words += mailbox->count;
if ( mailbox == &args1)
pthread_join(t1,NULL);
if ( mailbox == &args2)
pthread_join(t2,NULL);
if ( mailbox == &args3)
pthread_join(t3,NULL);

mailbox = NULL;
printf("MAIN: Ok,I have read the mail\n");
sem_post(&sem_read);
reports_in++;
}

printf("%7d: total words\n", total_words);
sem_destroy(&sem_read);
sem_destroy(&sem_write);

pthread_win32_thread_detach_np();
pthread_win32_process_detach_np();

system("pause");
}

void *count_words(void *a)
{
struct arg_set *args = (arg_set *)a;    /* cast arg back to correct type */
FILE *fp;
int  c, prevc = '\0';

if ( (fp = fopen(args->fname, "r")) != NULL )
{
while( ( c = getc(fp)) != EOF )
{
if ( !isalnum(c) && isalnum(prevc) )
{
args->count++;
}
prevc = c;
}
fclose(fp);
} else
perror(args->fname);
printf("COUNT %d: waiting for main thread read the mail\n", args->tid);
sem_wait(&sem_read);
printf("COUNT %d:OK,I can write mail\n", args->tid);
mailbox = args;            /* put ptr to our args there */
printf("COUNT %d: Finished writting\n", args->tid);
sem_post(&sem_write);
return NULL;
}

http://www.cppblog.com/saha/articles/189802.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: