1:线程与进程的区别
2:线程同步:互斥锁
3:线程同步:条件变量
4:线程同步:post信号量
在代码中有实例。
5:线程退出
6:线程示例代码
/*
============================================================================
Name : threadDemo.c
Author :
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
#include <syslog.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <stddef.h> /* For definition of offsetof() */
#include <stdarg.h> /* For definition of offsetof() */
#include <limits.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h> /* Type definitions used by many programs */
#include <stdio.h> /* Standard I/O functions */
#include <stdlib.h> /* Prototypes of commonly used library functions,
plus EXIT_SUCCESS and EXIT_FAILURE constants */
#include <unistd.h> /* Prototypes for many system calls */
#include <errno.h> /* Declares errno and defines error constants */
#include <string.h> /* Commonly used string-handling functions */
#include <sys/param.h>
#include <pthread.h>
#include <semaphore.h>
typedef enum { FALSE, TRUE } Boolean;
/*
使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式。我们知道,在Linux 系统下,
启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,
这是一种"昂贵"的多任务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,
共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切
换所需的时间也远远小于进程间切换所需要的时间。据统计,总的说来,一个进程的开销大约是一个线程
开销的30 倍左右,当然,在具体的系统上,这个数据可能会有较大的区别
*/
struct menber
{
int a;
char *s;
};
void cleanup(void *arg)
{
printf("cleanup arg:%s\n",arg);
}
void *thread_one(void *arg)
{
pid_t pid;
pthread_t tid;
pid=getpid();
tid=pthread_self();
struct menber *parameter=(struct menber *)arg;
pthread_cleanup_push(cleanup,(void*)parameter->s); //atexit();
printf("thread_one: the pid is %u ,the thread is %u \n",pid,tid);
printf("a:%d s:%s\n",parameter->a,parameter->s);
pthread_cleanup_pop(1); //pthread_cleanup_pop(0);//atexit();
pthread_exit((void *)parameter->a);
}
void *thread_two(void *arg)
{
pid_t pid;
pthread_t tid;
pid=getpid();
tid=pthread_self();
printf("thread_two: the pid is %u ,the thread is %u \n",pid,tid);
return (void*)8;
}
void pthreadParamter()
{
int err,stat_val;;
pid_t pid,childPid;
pthread_t tid_one,tid_two;
pid=getpid();
tid_one=pthread_self();
void *retValue_one,*retValue_two;
struct menber parameter;
parameter.a=123456;
parameter.s="suiyuan";
if((childPid=fork())==-1)
{
perror("fork");
exit(EXIT_FAILURE);
}
else if(childPid==0)
{
err=pthread_create(&tid_one,NULL,thread_one,(void *)¶meter);
if(err!=0)
{
printf("error message is:%s\n",strerror(err));
exit(1);
}
pthread_join(tid_one,&retValue_one);
printf("pthread_join,thread_one return value:%d\n",(int)retValue_one);
}
else
{
pthread_create(&tid_two,NULL,(void *)thread_two,NULL);
if(err!=0)
{
printf("error message is:%s\n",strerror(err));
exit(1);
}
pthread_join(tid_two,&retValue_two);
printf("pthread_join,thread_two return value:%d\n",(int)retValue_two);
printf("pid:%d getpid:%d\n",pid,getpid());
waitpid(childPid, &stat_val, 0);
if (WIFEXITED(stat_val))
{
printf("Child exited with code %d\n", WEXITSTATUS(stat_val));
}
else if (WIFSIGNALED(stat_val))
{
printf("Child terminated abnormally, signal %d\n", WTERMSIG(stat_val));
}
}
printf("main thread:the pid is %u ,the thread is %u \n",pid,tid_one);
}
/*
如果进程中任何一个线程中调用exit,_Exit,或者是_exit,那么整个进程就会终止,
与此类似,如果信号的默认的动作是终止进程,那么,把该信号发送到线程会终止进程。
线程的正常退出的方式:
(1) 线程只是从启动例程中返回,返回值是线程中的退出码
(2) 线程可以被另一个进程进行终止
(3) 线程自己调用pthread_exit 函数
*/
//************************************************************************************************
#if 1
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
#endif
#if 1
static int avail = 0;
static void *pthread_mutex_lock_Func(void *arg)
{
int cnt = *((int *) arg);
int s, j;
printf("pthread_mutex_lock_Func:arg:%d\n",cnt);
sleep(1);
for (j = 0; j < cnt; j++) {
sleep(2);
/* Code to produce a unit omitted */
s = pthread_mutex_lock(&mtx);
if (s != 0)
perror("pthread_mutex_lock");
avail++; /* Let consumer know another unit is available */
s = pthread_mutex_unlock(&mtx);
if (s != 0)
perror("pthread_mutex_unlock");
#if 1
s = pthread_cond_signal(&cond); /* Wake sleeping consumer */
if (s != 0)
perror("pthread_cond_signal");
#endif
}
return NULL;
}
void pthread_mutex_lock_test(int num)
{
pthread_t tid;
int s;
int totRequired; /* Total number of units that all threads will produce */
int numConsumed; /* Total units so far consumed */
Boolean done;
time_t t;
t = time(NULL);
/* Create all threads */
{
totRequired = num;
printf("totRequired:%d\n",totRequired);
s = pthread_create(&tid, NULL, pthread_mutex_lock_Func, (void *)&totRequired);
if (s != 0)
perror("pthread_create");
}
/* Use a polling loop to check for available units */
numConsumed = 0;
done = FALSE;
for (;;) {
s = pthread_mutex_lock(&mtx);
if (s != 0)
{
perror("pthread_mutex_lock");
}
// while (avail == 0)
{ /* Wait for something to consume */
s = pthread_cond_wait(&cond, &mtx);
if (s != 0)
perror("pthread_cond_wait");
}
// while (avail > 0)
{ /* Consume all available units */
/* Do something with produced unit */
numConsumed ++;
printf("condition is ture;T=%ld: avail=%d numConsumed=%d\n", (long) (time(NULL) - t),avail,numConsumed);
avail--;
done = numConsumed >= totRequired;
}
s = pthread_mutex_unlock(&mtx);
if (s != 0)
{
perror("pthread_mutex_unlock");
}
if (done)
{
break;
}
/* Perhaps do other work here that does not require mutex lock */
}
exit(EXIT_SUCCESS);
}
#endif
//***************************************condition example***********************************************
#if 1
/*
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
*/
static int glob = 0;
static void cleanupHandler(void *arg) /* Free memory pointed to by 'arg' and unlock mutex */
{
int s;
printf("cleanup: freeing block at %p\n", arg);
free(arg);
printf("cleanup: unlocking mutex\n");
s = pthread_mutex_unlock(&mtx);
if (s != 0)
perror("pthread_mutex_unlock");
}
static void *mutex_conditionFunc(void *arg)
{
int s;
void *buf = NULL; /* Buffer allocated by thread */
buf = malloc(0x10000); /* Not a cancellation point */
printf("thread: allocated memory at %p\n", buf);
s = pthread_mutex_lock(&mtx); /* Not a cancellation point */
if (s != 0)
{
perror("pthread_mutex_lock");
}
pthread_cleanup_push(cleanupHandler, buf);
// while (glob == 0)
{
printf("pthread_cond_wait become to ture\n");
s = pthread_cond_wait(&cond, &mtx); /* A cancellation point */
if (s != 0)
{
perror("pthread_cond_wait");
}
}
printf("thread: condition wait loop completed\n");
pthread_cleanup_pop(1); /* Executes cleanup handler */
return NULL;
}
void mutex_condition_test(int argc)
{
pthread_t thr;
void *res;
int s;
s = pthread_create(&thr, NULL, mutex_conditionFunc, NULL);
if (s != 0)
{
perror("pthread_create");
}
printf("main: sleep 5s\n");
sleep(5); /* Give thread a chance to get started */
if (argc == 1)
{ /* Cancel thread */
printf("main: about to cancel thread\n");
s = pthread_cancel(thr);
if (s != 0)
{
perror("pthread_cancel");
}
} else
{ /* Signal condition variable */
printf("main: about to signal condition variable\n");
glob = 1;
s = pthread_cond_signal(&cond);
if (s != 0)
{
perror("pthread_cond_signal");
}
}
s = pthread_join(thr, &res);
if (s != 0)
perror("pthread_join");
if (res == PTHREAD_CANCELED)
printf("main: thread was canceled\n");
else
printf("main: thread terminated normally\n");
exit(EXIT_SUCCESS);
}
#endif
static int globCount = 0;
static sem_t postsem;
static void * threadPostSemaphoresFunc(void *arg) /* Loop 'arg' times incrementing 'glob' */
{
int loops = *((int *) arg);
int loc, j;
for (j = 0; j < loops; j++) {
if (sem_wait(&postsem) == -1)
perror("sem_wait");
loc = globCount;
loc++;
globCount = loc;
printf("threadPostSemaphoresFunc:loops %d globCount %d\n",loops, globCount);
sleep(1);
if (sem_post(&postsem) == -1)
perror("sem_post");
}
return NULL;
}
void threadAndPostSemaphoresTest(int loops)
{
pthread_t t1, t2;
int s,loops1=loops+1;
/* Initialize a semaphore with the value 1 */
if (sem_init(&postsem, 0, 1) == -1)
perror("sem_init");
/* Create two threads that increment 'glob' */
s = pthread_create(&t1, NULL, threadPostSemaphoresFunc, &loops1);
if (s != 0)
perror("pthread_create");
s = pthread_create(&t2, NULL, threadPostSemaphoresFunc, &loops);
if (s != 0)
perror("pthread_create");
/* Wait for threads to terminate */
s = pthread_join(t1, NULL);
if (s != 0)
perror("pthread_join");
s = pthread_join(t2, NULL);
if (s != 0)
perror("pthread_join");
printf("globCount = %d\n", globCount);
exit(EXIT_SUCCESS);
}
usageError(const char *progName, const char *msg)
{
if (msg != NULL)
{
fprintf(stderr, "%s", msg);
}
fprintf(stderr, "Usage: %s [options] parameter\n", progName);
fprintf(stderr, "Usage: %s [tm:c:p:] parameter\n", progName);
fprintf(stderr, "Usage: %s -t ;to execute:pthreadParamter()\n", progName);
fprintf(stderr, "Usage: %s -m parameter;to execute:pthread_mutex_lock_test()\n", progName);
fprintf(stderr, "Usage: %s -c [parameter];to execute:mutex_condition_test()\n", progName);
fprintf(stderr, "Usage: %s -p parameter;to execute:threadAndPostSemaphoresTest()\n", progName);
fprintf(stderr, "Usage: %s -h ;to execute:help\n", progName);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[])
{
int opt;
if(argc==1)
{
perror("");
usageError(argv[0], NULL);
}
while ((opt = getopt(argc, argv, "tm:c:k:p:")) != -1) {
switch (opt) {
case 't':
pthreadParamter();
break;
case 'm':
if(optarg!=NULL)
{
printf("optopt:%c :%d\n",optopt,atoi(optarg));
pthread_mutex_lock_test(atoi(optarg));
}
else
{
usageError(argv[0], NULL);
}
break;
case 'c':
if(optarg!=NULL)
{
printf("optopt:%c :%d\n",optopt,atoi(optarg));
mutex_condition_test(atoi(optarg));
}
else
{
usageError(argv[0], NULL);
}
break;
case 'p':
if(optarg!=NULL)
{
printf("optopt:%c :%d\n",optopt,atoi(optarg));
threadAndPostSemaphoresTest(atoi(optarg));
}
else
{
usageError(argv[0], NULL);
}
break;
default:
usageError(argv[0], NULL);
}
}
return EXIT_SUCCESS;
}