Linux下一般使用POSIX线程库,也叫pthread。编写线程函数需要注意的是线程函数的返回类型必须是void*;程序编译的时候记得要链接上pthread库,方法:-lpthread
下面是简单的线程程序,主程序里创建了2个线程,分别打印不同的信息。每个线程用pthread_create函数来创建。每个线程运行完程序之后,必须使用pthread_join函数来等待线程结束,也就是回收线程。一旦两个线程都退出后,主程序就会退出。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
void error(char *msg)
{
fprintf(stderr, "%s : %s\n", msg, strerror(errno) );
exit(1);
}
void* hello(void *a)
{
int i = 0;
for(i = 0; i < 5; i++)
{
sleep(1);
puts("hello linux!");
}
return NULL;
}
void* goodbye(void *a)
{
int i = 0;
for(i = 0; i < 5; i++)
{
sleep(1);
puts("goodbye linux!");
}
return NULL;
}
int main(int argc, char const *argv[])
{
pthread_t t0;
pthread_t t1;
if(pthread_create(&t0, NULL, hello, NULL) == -1)
error("cant creat pthread t0");
if(pthread_create(&t1,NULL, goodbye, NULL) == -1)
error("cant creat pthread t1");
void* result;
if(pthread_join(t0, &result) == -1)
error("cant join pthread t0");
if(pthread_join(t1, &result) == -1)
error("cant join pthread t1");
return 0;
}
如果编译程序没有添加-lpthread,就会出现下面的错误
root@zengwh:~/test_code# gcc -Wall pthread.c -o pthread
/tmp/cc5KEYbr.o:在函数‘main’中:
pthread.c:(.text+0xec):对‘pthread_create’未定义的引用
pthread.c:(.text+0x116):对‘pthread_create’未定义的引用
pthread.c:(.text+0x138):对‘pthread_join’未定义的引用
pthread.c:(.text+0x15a):对‘pthread_join’未定义的引用
collect2: error: ld returned 1 exit status
成功编译后,结果如下:
root@zengwh:~/test_code# gcc -Wall pthread.c -lpthread -o pthread
root@zengwh:~/test_code# ./pthread
goodbye linux!
hello linux!
goodbye linux!
hello linux!
goodbye linux!
hello linux!
hello linux!
goodbye linux!
hello linux!
goodbye linux!
下面的程序,同时创建10个线程,每个线程公用一个函数,都是将全局变量number 减1000,等所有线程结束之后,再打印出变量的值,看是否等于0.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
int number = 10000;
void error(char *msg)
{
fprintf(stderr, "%s : %s\n", msg, strerror(errno) );
exit(1);
}
void* func(void *a)
{
int i = 0;
for (i = 0; i < 1000; ++i)
{
number -= 1;
}
return NULL;
}
int main(int argc, char const *argv[])
{
pthread_t thread[10];
int j = 0;
printf("begining: the number is : %d\n", number );
for (j = 0; j < 10; ++j)
{
if (pthread_create(&thread[j], NULL, func, NULL) == -1)
error("cant creat pthread t0");
}
void* result;
for (j = 0; j < 10; ++j)
{
if (pthread_join(thread[j], &result) == -1)
error("cant creat pthread t0");
}
printf("finally: the number is : %d\n", number );
return 0;
}
程序运行结果如下:
root@zengwh:~/test_code# ./pthread
begining: the number is : 10000
finally: the number is : 882
root@zengwh:~/test_code# ./pthread
begining: the number is : 10000
finally: the number is : 801
root@zengwh:~/test_code# ./pthread
begining: the number is : 10000
finally: the number is : 501
root@zengwh:~/test_code# ./pthread
begining: the number is : 10000
finally: the number is : 634
root@zengwh:~/test_code# ./pthread
begining: the number is : 10000
finally: the number is : 887
每次运行的结果都不一样。线程最大的优点在于可以同时运行多个不同任务,并访问相同的数据,但访问相同的数据也成为了线程的缺点。上面程序的结果就是线程撞车,结果是不可预测的。
为了让多个线程可以访问共享数据且不会发生撞车,一种简单办法就是创建互斥锁。
pthread_mutex_t a_lock = PTHREAD_MUTEX_INITIALIZER;
互斥锁必须是一个全局变量,这样才能对所有有可能发生撞车的线程可见。pthread_mutex_lock()函数只允许一个线程运行,其他线程处于等待。然后调用pthread_mutex_unlock()函数解锁,其他线程可以进入。
pthread_mutex_lock(&a_lock);
/*需要访问的共享数据*/
pthread_mutex_unlock(&a_lock);
增加锁后的程序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
int number = 10000;
pthread_mutex_t number_lock = PTHREAD_MUTEX_INITIALIZER;
void error(char *msg)
{
fprintf(stderr, "%s : %s\n", msg, strerror(errno) );
exit(1);
}
void* func(void *a)
{
int i = 0;
pthread_mutex_lock(&number_lock);
for (i = 0; i < 1000; ++i)
{
number -= 1;
}
pthread_mutex_unlock(&number_lock);
printf("the number is : %d\n", number );
return NULL;
}
int main(int argc, char const *argv[])
{
pthread_t thread[10];
int j = 0;
printf("begining: the number is : %d\n", number );
for (j = 0; j < 10; ++j)
{
if (pthread_create(&thread[j], NULL, func, NULL) == -1)
error("cant creat pthread t0");
}
void* result;
for (j = 0; j < 10; ++j)
{
if (pthread_join(thread[j], &result) == -1)
error("cant creat pthread t0");
}
printf("finally: the number is : %d\n", number );
return 0;
}