linux多线程运行机制
时间:2009-02-26 来源:zjutlyp
多线程主要用于解决单线程可能出现的阻塞问题;以达到对CPU的充分利用。下面介绍多线程主要涉及到的一些系统调用。
1、建立线程
#include <pthread.h> int pthread_create(
pthread_t *thread_id, /* new thread's ID */
const pthread_attr_t *attr, /* attributes (or NULL) */
void *(*start_fcn)(void *), /* start function */
void *arg /* arg to starting function */
);
/* Return 0 on success, error number on error */
新线程从p_thread_create中规定的启动函数的调用开始,该函数必须具有如下原型:
void *start_fcn(void *arg);
无论向pthread_create函数的第4个参数传递什么值,都将被直接传给那个启动函数。通常它是一个void指针,而实际上经常是指向某个数据的指针。因为线程共享同样的地址空间,所以该指针对两个进程都是有效的。如果愿意,也可以以整形数据类型传递参数,但必须要将它转换给某个void指针。并且为了安全,应该检查使用的整形类型是否和void指针相适应:
assert(sizeof(long) <= sizeof(void *));
pthread函数一律在成功时返回0,而失败时返回错误代码,但不设置errno,对于这个问题,可以使用ec宏里面的ec_rv来解决。 2、等待线程终止
int pthread_join(
pthread_t thread_id, /* ID of thread to join */
void **status_ptr /* returned exit status (if not NULL arg) */
);
/* Return 0 on success, error number on error */ 3、线程同步(互斥)
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); 4、条件变量
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *cond); 5、取消线程
int pthread_cancel(pthread_t *thread_id); 6、清除处理程序
void pthread_cleanup_push(void (*handler)(void*), void *arg);
void pthread_cleanup_pop(int execute); 7、信号灯 #include <semaphore.h> int sem_init(sem_t *sem, int pshared, unsigned int value);
这是创建信号灯的API,其中value为信号灯的初值,pshared表示是否为多进程共享而不仅仅是用于一个进程。LinuxThreads没有实现多进程共享信号灯,因此所有非0值的pshared输入都将使sem_init()返回-1,且置errno为ENOSYS。初始化好的信号灯由sem变量表征,用于以下点灯、灭灯操作。
int sem_destroy(sem_t * sem);
被注销的信号灯sem要求已没有线程在等待该信号灯,否则返回-1,且置errno为EBUSY。除此之外,LinuxThreads的信号灯注销函数不做其他动作。
int sem_post(sem_t * sem);
int sem_wait(sem_t * sem);
int sem_trywait(sem_t * sem);
int sem_getvalue(sem_t * sem, int * sval);
下面是一个关于多线程的例子:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h> static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; struct node {
int n_number;
struct node* next;
} *head = NULL; static void cleanup_handler(void *arg)
{
free(arg);
(void)pthread_mutex_unlock(&mtx);
} static void *thread_func(void *arg)
{
struct node *p = NULL;
pthread_cleanup_push(cleanup_handler, p); /* 安装清除处理程序,在线程被cancle后对互斥锁进行解锁 */
while (1) {
pthread_mutex_lock(&mtx);
while (head == NULL)
pthread_cond_wait(&cond, &mtx);
p = head;
head = head->next;
printf("Got %d from front of queue\n", p->n_number);
free(p);
pthread_mutex_unlock(&mtx);
}
pthread_cleanup_pop(0);
return (void *)1;
} int main(void)
{
pthread_t tid;
int i;
struct node *p;
pthread_create(&tid, NULL, thread_func, NULL);
for (i = 0; i < 5; i++) {
p = malloc(sizeof(struct node));
p->n_number = i;
pthread_mutex_lock(&mtx);
p->next = head;
head = p;
pthread_mutex_unlock(&mtx);
pthread_cond_signal(&cond);
sleep(1);
}
pthread_cancel(tid); /* 防止子线程死锁 */
pthread_join(tid, NULL);
printf("All done -- exiting\n");
return EXIT_SUCCESS;
} 运行结果:
$ gcc -lpthread ext.c -o ext
$ ./ext
Got 0 from front of queue
Got 1 from front of queue
Got 2 from front of queue
Got 3 from front of queue
Got 4 from front of queue
All done -- exiting
#include <pthread.h> int pthread_create(
pthread_t *thread_id, /* new thread's ID */
const pthread_attr_t *attr, /* attributes (or NULL) */
void *(*start_fcn)(void *), /* start function */
void *arg /* arg to starting function */
);
/* Return 0 on success, error number on error */
新线程从p_thread_create中规定的启动函数的调用开始,该函数必须具有如下原型:
void *start_fcn(void *arg);
无论向pthread_create函数的第4个参数传递什么值,都将被直接传给那个启动函数。通常它是一个void指针,而实际上经常是指向某个数据的指针。因为线程共享同样的地址空间,所以该指针对两个进程都是有效的。如果愿意,也可以以整形数据类型传递参数,但必须要将它转换给某个void指针。并且为了安全,应该检查使用的整形类型是否和void指针相适应:
assert(sizeof(long) <= sizeof(void *));
pthread函数一律在成功时返回0,而失败时返回错误代码,但不设置errno,对于这个问题,可以使用ec宏里面的ec_rv来解决。 2、等待线程终止
int pthread_join(
pthread_t thread_id, /* ID of thread to join */
void **status_ptr /* returned exit status (if not NULL arg) */
);
/* Return 0 on success, error number on error */ 3、线程同步(互斥)
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); 4、条件变量
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *cond); 5、取消线程
int pthread_cancel(pthread_t *thread_id); 6、清除处理程序
void pthread_cleanup_push(void (*handler)(void*), void *arg);
void pthread_cleanup_pop(int execute); 7、信号灯 #include <semaphore.h> int sem_init(sem_t *sem, int pshared, unsigned int value);
这是创建信号灯的API,其中value为信号灯的初值,pshared表示是否为多进程共享而不仅仅是用于一个进程。LinuxThreads没有实现多进程共享信号灯,因此所有非0值的pshared输入都将使sem_init()返回-1,且置errno为ENOSYS。初始化好的信号灯由sem变量表征,用于以下点灯、灭灯操作。
int sem_destroy(sem_t * sem);
被注销的信号灯sem要求已没有线程在等待该信号灯,否则返回-1,且置errno为EBUSY。除此之外,LinuxThreads的信号灯注销函数不做其他动作。
int sem_post(sem_t * sem);
int sem_wait(sem_t * sem);
int sem_trywait(sem_t * sem);
int sem_getvalue(sem_t * sem, int * sval);
下面是一个关于多线程的例子:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h> static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; struct node {
int n_number;
struct node* next;
} *head = NULL; static void cleanup_handler(void *arg)
{
free(arg);
(void)pthread_mutex_unlock(&mtx);
} static void *thread_func(void *arg)
{
struct node *p = NULL;
pthread_cleanup_push(cleanup_handler, p); /* 安装清除处理程序,在线程被cancle后对互斥锁进行解锁 */
while (1) {
pthread_mutex_lock(&mtx);
while (head == NULL)
pthread_cond_wait(&cond, &mtx);
p = head;
head = head->next;
printf("Got %d from front of queue\n", p->n_number);
free(p);
pthread_mutex_unlock(&mtx);
}
pthread_cleanup_pop(0);
return (void *)1;
} int main(void)
{
pthread_t tid;
int i;
struct node *p;
pthread_create(&tid, NULL, thread_func, NULL);
for (i = 0; i < 5; i++) {
p = malloc(sizeof(struct node));
p->n_number = i;
pthread_mutex_lock(&mtx);
p->next = head;
head = p;
pthread_mutex_unlock(&mtx);
pthread_cond_signal(&cond);
sleep(1);
}
pthread_cancel(tid); /* 防止子线程死锁 */
pthread_join(tid, NULL);
printf("All done -- exiting\n");
return EXIT_SUCCESS;
} 运行结果:
$ gcc -lpthread ext.c -o ext
$ ./ext
Got 0 from front of queue
Got 1 from front of queue
Got 2 from front of queue
Got 3 from front of queue
Got 4 from front of queue
All done -- exiting
#include <pthread.h> |
#include <pthread.h> |
相关阅读 更多 +
排行榜 更多 +