<!-- @page { margin: 2cm } PRE { font-family: "AR PL UKai CN" } P { margin-bottom: 0.21cm } -->
多线程
-、主要函数:
二、
1、cpu调度的基本单位是线程。线,进程对于kernel而言没有什么区别,在内核里有相应的task_struct(任务描述符)
线程与进程:1)调度一样2)线程的创建成本会快一些
2、线程,地址空间是共享的
pthread_self();
pthread_create();
pthread_exit(NULL);
pthread_join(tid,NULL);
创建多个线程: pthread tid[5] ; pthread_create(tid+i,NULL,thread_handler,NULL);
用堆分配,不要用栈,用栈不保险。
栈-->私有,只要函数退出,栈的东西就没有了,所以尽量不要返回栈里的东西的地址!
线程有点普通函数的感觉。线程共享文件描述符表。
3、线程锁
1)初始化:动态/静态
2)lock,unlock
3)消毁一把锁
lock代码段,加锁的目的,保护数据
锁应是一个全局变量。全局锁-----互斥锁
如果已锁,你再去lock,那么会使你阻塞,不占用cpu
FILE* fp=fdopen(fd,”r+”);将fd转换成FILE*型
4、线程的条件变量
在修改全局变量的地方加锁,完了后解锁,发信号
pthread_cond_wait(&g_cond,&g_lock)解锁、休眠;被唤醒后,加锁、执行(原子操作)
signal:只是唤醒某一个线程
broadcast:所有线程都会起来
5、线程的分离属性
1)创建的时候就设置其为分离属性2)用pthread_detach()自己分离属性
pthread_attr_init(&attr)将attr初始化为默认属性
pthread_attr_setdetach()设置分离
设成分离属性后就不能----join了
三、例程
1、
/*pthread_create.c*/
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void *thread_handler(void *arg)
{
printf("pid=%d/n", getpid());
//exit(0);
while (1)
sleep(1);
return NULL;
}
int main(void)
{
pthread_t tid;
int ret;
ret = pthread_create(&tid, NULL, thread_handler,
NULL);
if (ret) {
printf("%s/n", strerror(ret));
exit(1);
}
while (1)
sleep(1);
printf("pid=%d/n", getpid());
//}
exit(0);
}
2、
/*pthread_exit.c*/
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void *thread_handler(void *arg)
{
printf("pid=%d/n", getpid());
pthread_exit(NULL);
}
int main(void)
{
pthread_t tid;
int ret;
ret = pthread_create(&tid, NULL, thread_handler,
NULL);
if (ret) {
printf("%s/n", strerror(ret));
exit(1);
}
pthread_exit(NULL);
}
3、
/*pthread_join.c*/
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
static int mul=0;
void *thread_handler(void *arg)
{
char buf[5];
bzero(buf, 5);
write(1, "Please input mul: ", 19);
read(0, buf, 4);
mul =atoi(buf);
return NULL;
// pthread_exit(NULL);
}
int main(void)
{
pthread_t tid;
int ret;
ret = pthread_create(&tid, NULL, thread_handler,
NULL);
if (ret) {
printf("%s/n", strerror(ret));
exit(1);
}
while (1)
ret++;
pthread_join(tid, NULL);
printf("ret=%d/n", 5*mul);
pthread_exit(NULL);
}
/*可用return NULL代替pthread_exit(NULL)*/
4、
/*创建5个线程*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
void *thread_handler(void *arg)
{
// int value = *((int *)(arg));
int value = (int)arg;
printf("value=%d/n", value);
return NULL;
}
int main(void)
{
int i, ret;
pthread_t tid[5];
int *a = (int *)malloc(5*sizeof(int));
for (i = 0; i < 5; i++) {
// a[i] = i;
ret = pthread_create(tid+i, NULL,
thread_handler, (void *)i);// (void *)i玩无间道,欺骗编译器。本来i是int型的,将其当作(void*)型传进去.
if (ret) {
printf("%s/n", strerror(ret));
exit(1);
}
}
pthread_exit(NULL);
for(i = 0; i < 5; i++) {
pthread_join(tid[i], NULL);
}
free(a);
pthread_exit(NULL);
}
5、
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
int fd;
void *thread_handler(void *arg)
{
close(fd);
return NULL;
}
int main(void)
{
pthread_t tid;
int ret;
char buf[100];
ret = pthread_create(&tid, NULL,
thread_handler, NULL);
if (ret) {
printf("%s/n", strerror(ret));
exit(1);
}
fd = open("/etc/passwd", O_RDONLY);
if (fd == -1) {
perror("open");
exit(1);
}
pthread_join(tid, NULL);
ret = read(fd, buf, 100);
if (ret == -1) {
perror("read");
exit(1);
}
write(1, buf, ret);
pthread_exit(NULL);
}
/*线程共享很多东西*/
6、
/*线程锁(互斥)*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
int fd;
pthread_mutex_t glock;//用全局锁,同一时刻只能由一个线程上锁
void *thread_handler(void *arg)
{
char buf[20];
pthread_mutex_lock(&glock);
lseek(fd, 0, SEEK_SET);
FILE *fp = fdopen(fd, "r+");//将fd转换成FILE*型
if (fp == NULL) {
perror("fdopen");
exit(1);
}
fgets(buf, 20, fp);
printf("%s", buf);
lseek(fd, 0, SEEK_SET);
pthread_mutex_unlock(&glock);
return NULL;
}
void main_thread_work(void)
{
pthread_mutex_lock(&glock);
lseek(fd, 0, SEEK_SET);
int i = 0;
char buf[3];
while (1) {//写0,1,2,3,4,5,6,7,8,9
sprintf(buf, "%d/n", i++);//'/n'也是占一个字符!
if (strlen(buf) == 3)
break;
write(fd, buf, 2);
sleep(2);
}
pthread_mutex_unlock(&glock);
}
int main(void)
{
pthread_t tid;
int ret;
char buf[100];
pthread_mutex_init(&glock, NULL);//构造一个互斥,生成一个互斥锁glock
ret = pthread_create(&tid, NULL,
thread_handler, NULL);
if (ret) {
printf("%s/n", strerror(ret));
exit(1);
}
fd = open("tmp", O_RDWR | O_CREAT | O_TRUNC,
0777);
if (fd == -1) {
perror("creat");
exit(1);
}
main_thread_work();
pthread_exit(NULL);
}
7、
/*条件变量*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <fcntl.h>
#include <unistd.h>
long long g_value;
#define THREADNUM 5
#define BASE 300000000
pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;//锁静态初始化
pthread_cond_t g_cond = PTHREAD_COND_INITIALIZER;//条件变量静态初始化
static void do_prime()
{
long long i;
int flag = 0;
for (i = 2; i < g_value; i++) {
if (g_value % i == 0) {
flag = 1;
break;
}
}
if (flag == 0) {
printf("%lld is a prime!/n", g_value);
} else
printf("%lld is not a prime!/n", g_value);
}
void *thread_handler(void *arg)
{
while (1) {
pthread_mutex_lock(&g_lock);
pthread_cond_wait(&g_cond, &g_lock);//上来先解锁,休眠;被唤醒后,加锁,往下执行
do_prime();
pthread_mutex_unlock(&g_lock);
}
return NULL;
}
int main(void)
{
int i, ret, value;
pthread_t tid[5];
for (i = 0; i < THREADNUM; i++) {
ret = pthread_create(tid+i, NULL,
thread_handler, NULL);
if (ret) {
printf("%s/n", strerror(ret));
exit(1);
}
}
while (1) {
printf("Please input the prime:");
fflush(stdout);
scanf("%d", &value);
pthread_mutex_lock(&g_lock);
g_value = BASE + value;
pthread_mutex_unlock(&g_lock);
pthread_cond_signal(&g_cond);//对保护部分处理完后,发信号//signal只是唤醒某一个线程
}
}
8、
/*broadcast.c*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <fcntl.h>
#include <unistd.h>
long long g_value;
#define THREADNUM 5
#define BASE 300000000
pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t g_cond = PTHREAD_COND_INITIALIZER;
static void do_prime()
{
long long i;
int flag = 0;
for (i = 2; i < g_value; i++) {
if (g_value % i == 0) {
flag = 1;
break;
}
}
if (flag == 0) {
printf("%lld is a prime!/n", g_value);
} else
printf("%lld is not a prime!/n", g_value);
}
void *thread_handler(void *arg)
{
pthread_mutex_lock(&g_lock);
pthread_cond_wait(&g_cond, &g_lock);
pthread_mutex_unlock(&g_lock);
printf("I am %d, exit!/n", (int)arg);
return NULL;
}
int main(void)
{
int i, ret, value;
pthread_t tid[5];
for (i = 0; i < THREADNUM; i++) {
ret = pthread_create(tid+i, NULL,
thread_handler, (void *)i);
if (ret) {
printf("%s/n", strerror(ret));
exit(1);
}
}
sleep(3);
//pthread_cond_signal(&g_cond);
pthread_cond_broadcast(&g_cond);
pthread_exit(NULL);
}
/*pthread_cond_signal(&g_cond);pthread_cond_broadcast(&g_cond);
signal: 只是唤醒某一个线程,谁先抢到就是谁的。
broadcast:所有线程都会起来
*/
9、/*attr.c*//*分离属性*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
void *thread_handler(void *arg)
{
pthread_detach(pthread_self());
sleep(5);
return NULL;
}
int main(void)
{
pthread_attr_t attr;
pthread_t tid;
pthread_attr_init(&attr);
// pthread_attr_setdetachstate(&attr,
// PTHREAD_CREATE_DETACHED);
int ret = pthread_create(&tid, &attr,
thread_handler, NULL);
if (ret) {
fprintf(stderr, "%s/n", strerror(ret));
exit(1);
}
#if 1
usleep(10);
printf("join!/n");
ret = pthread_join(tid, NULL);
if (ret) {
fprintf(stderr, "%s/n", strerror(ret));
pthread_exit(NULL);
}
printf("join!/n");
#endif
pthread_attr_destroy(&attr);
pthread_exit(NULL);
}