參考至
http://sourceware.org/pthreads-win32/manual/index.html,其中包括pthread的win32,winc3實現(xiàn)(基本跨平臺)
pthread介紹:
https://computing.llnl.gov/tutorials/pthreads/基本接口介紹:
1. pthread_create
#include <pthread.h>
int pthread_create(pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg);
創(chuàng)建一個由調(diào)用線程控制的新的線程并發(fā)運行。新的線程使用
start_routine作為實現(xiàn)體,并以
arg作為第一個參數(shù)。
新的線程可以通過調(diào)用pthread_exit顯式結(jié)束,或者通過
start_routine return來隱式結(jié)束。其中后者等價于調(diào)用pthread_exit并以
start_routine 的返回值作為退出碼。
新線程的初始信號狀態(tài)繼承自他的創(chuàng)建線程,并且沒有掛起的信號。pthread-win32暫時未實現(xiàn)信號量。
attr參數(shù)指明新線程的屬性,如果attr=NULL,則使用默認屬性:新線程是joinable(not detached),和默認的調(diào)度策略(非實時)
返回值:如果成功,新線程的指針會被存儲到
thread的參數(shù)中,并返回0。如果錯誤則一個非0的錯誤碼返回。
如果返回EAGAIN,沒有足夠的系統(tǒng)資源創(chuàng)建一個線程,或者已經(jīng)存在大于
PTHREAD_THREADS_MAX個活躍線程。
2. pthread_exit
#include <pthread.h>
void pthread_exit(void *retval);
pthread_exit結(jié)束調(diào)用線程的執(zhí)行.所有通過pthread_cleanup_push設(shè)置的清除句柄將會被反序執(zhí)行(后進先出)。
所以key值非空的線程特定數(shù)據(jù)Finalization functions被調(diào)用(參見pthread_key_create)。
最后調(diào)用線程被終止。
retval是這個線程結(jié)束的返回值,可以通過在別的線程中調(diào)用pthread_join來獲取這個值。
沒有返回值。
3. pthread_join
#include <pthread.h>
int pthread_join(pthread_t th, void **thread_return);
掛載一個在執(zhí)行的線程直到該線程通過調(diào)用pthread_exit或者cancelled結(jié)束。
如果thread_return不為空,則線程th的返回值會保存到thread_return所指的區(qū)域。
th的返回值是它給pthread_exit的參數(shù),或者是pthread_canceled 如果是被cancelled的。
被依附的線程th必須是joinable狀態(tài)。一定不能是detached通過使用pthread_detach或者pthread_create中使用pthread_create_detached屬性。
當一個joinable線程結(jié)束時,他的資源(線程描述符和堆棧)不會被釋放直到另一個線程對它執(zhí)行pthread_join操作。
如果成功,返回值存儲在thread_return中,并返回0,否則返回錯誤碼:
ESRCH:找不到指定線程
EINVAL:線程th是detached或者已經(jīng)存在另一個線程在等待線程th結(jié)束
EDEADLK:th的參數(shù)引用它自己(即線程不能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是一種一個線程可以結(jié)束另一個線程執(zhí)行的機制。更確切的說,一個線程可以發(fā)生Cancellation請求給另一個線程。
根據(jù)線程的設(shè)置,收到請求的線程可以忽視這個請求,立即執(zhí)行這個請求或者延遲到一個cancellation點執(zhí)行。
當一個線程執(zhí)行Cancellation請求,相當于在那個點執(zhí)行pthread_exit操作退出:所有cleanup句柄被反向調(diào)用,所有析構(gòu)函數(shù)被調(diào)用結(jié)束線程并返回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靜態(tài)初始化。
pthread_cond_signal激活一個正在等待條件變量cond的線程。如果沒有線程在等待則什么也不會發(fā)生,如果有多個線程在等待,則只能激活一個線程,帶未指定是哪個線程(根據(jù)操作系統(tǒng)自己的調(diào)度策略選擇)。
pthread_cond_broadcast激活所有在等待條件變量cond的線程。
pthread_cond_wait自動解鎖mutex(pthread_unlock_mutex)等待條件變量cond發(fā)送。線程的執(zhí)行被掛起不消耗cpu時間直到cond發(fā)送。在wait的入口mutex必須被鎖住。
在重新回到線程前,pthread_cond_wait會重新獲得mutex(pthread_lock_mutex).解鎖mutex和掛起是自動進行的。因此,如果所有線程在發(fā)送cond前都申請mutex的話,
這種wait的內(nèi)部實現(xiàn)機制能夠保證在線程鎖住mutex和線程wait之間不會有cond發(fā)送操作發(fā)送。
pthread_cond_timedwait同pthread_cond_wait,只是多了個超時設(shè)置,如果超時,則重新獲取mutex并且返回ETIMEDOUT,時間為絕對時間。
pthread_cond_destroy銷毀一個條件變量。必須沒有線程在wait該條件變量。
condition函數(shù)是異步信號不安全的,容易產(chǎn)生死鎖,必須自己控制調(diào)用流程避免死鎖。
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,只是多了個超時設(shè)置,如果超時,首先將全局變量errno設(shè)為ETIMEDOUT,然后返回-1.
sem_trywait:如果信號量的值大于0,將信號量減1并立即返回,否則將全局變量errno設(shè)為ETIMEDOUT,然后返回-1。sem_trywait不會阻塞。
sem_post:釋放一個正在等待該信號量的線程,或者將該信號量+1.
sem_post_multiple:釋放多個正在等待的線程。如果當前等待的線程數(shù)n小于number,則釋放n個線程,并且該信號量的值增加(number - n).
sem_get_value:返回信號量的值。在pthread-win32實現(xiàn)中,正值表示當前信號量的值,負值的絕對值表示當前正在等待該信號量的線程數(shù)。雖然在POSIX不需要這么表示,但是也是同樣含義。
信號量(sem)與條件變量(cond)的主要差別在于,條件變量等待必須在發(fā)送之前,否則容易出現(xiàn)死鎖,而信號量等待可以在發(fā)送之后執(zhí)行。一句話概括信號量對于操作的時序沒有要求。
幾個測試程序:
1.
#include <stdio.h>
#include <Windows.h>
#include "pthread.h"
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥鎖*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*初始化條件變量*/
void *thread1(void *);
void *thread2(void *);
int i=1;
int main(void)
{
pthread_win32_process_attach_np();
pthread_win32_thread_attach_np();
pthread_t t_a;
pthread_t t_b;
pthread_create(&t_a,NULL,thread2,(void *)NULL);/*創(chuàng)建進程t_a*/
pthread_create(&t_b,NULL,thread1,(void *)NULL); /*創(chuàng)建進程t_b*/
pthread_join(t_b, NULL);/*等待進程t_b結(jié)束*/
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
pthread_win32_thread_detach_np();
pthread_win32_process_detach_np();
system("pause");
return 0;
}
void *thread1(void *junk)
{
for(i=1;i<=9;i++)
{
if(i%3==0)
{
pthread_mutex_lock(&mutex);/*鎖住互斥量*/
pthread_cond_signal(&cond);/*條件改變,發(fā)送信號,通知t_b進程*/
pthread_mutex_unlock(&mutex);/*解鎖互斥量*/
}
else
printf("thead1:%d\n",i);
}
return NULL;
}
void *thread2(void *junk)
{
while(i<9)
{
if(i%3!=0)
{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);/*等待*/
pthread_mutex_unlock(&mutex);
}
printf("thread2:%d\n",i);
}
return NULL;
}
結(jié)果:
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;
}
結(jié)果:
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;
}
4.
posted on 2012-09-07 13:41
saha 閱讀(12330)
評論(0) 編輯 收藏 引用