1、为什么用多线程?
并行处理任务,更快获得计算结果。
线程编程步骤:
1 线程id申明:pthread_t pid1;
2 线程创建函数:int ret=pthread_cread(&pid1, NULL, *Fuc, (void *)Fuc_args);
线程创建成功返回值为0,失败返回错误代码。
第一个参数是线程id地址;第二个参数是线程属性,值为NULL时表示使用线程默认属性;
第三个参数是线程函数入口地址(经测试该函数不用非得是空指针函数void * TestIp(void *args)????;
第四个参数是线程入口函数参数地址,1个参数传该参数的地址即可,多个参数用结构体地址来传递;
3 线程回收函数:pthread_join(pthread_t pid, NULL); 以阻塞的方式等待pid线程结束,并回收线程资源。
4 定义线程函数:(类型)Fuc { }
2、为什么加锁?
多线程访问共享资源时,为防止产生脏数据和错误而采取的方式。多线程访问同一个数据库时,数据库是共享资源,所以对库操作要加锁。
举例:1个厕所不能提供多人用,进入厕所加锁,使用完解锁,一个道理。
线程加锁步骤:
1 公共头文件a.h引用线程头文件 #include <pthread.h>
2 声明互斥锁的全局变量
extern phread_mutex_t sql_mutex;
3 宏定义加锁解锁操作
#define SQL_LOCK do{phread_mutex_lock(&sql_mutex);}while(0)
#define SQL_UNLOCK do{phread_mutex_unlock(&sql_mutex);}while(0)
4 代码引用头文件进行访问共享资源代码前一步加解锁操作,加锁太前了影响性能。
#include <a.h>
SQL_LOCK;
<操作共享数据>
SQL_UNLOCK;
3、线程编程及线程加解锁栗子:获取局域网内可用的IP并排序显示,15s左右出结果
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
int useful_ip_count = 0;
char *useful_ip[252] = {0};
char ip_net[128] = {0};
pthread_mutex_t data_mutex = PTHREAD_MUTEX_INITIALIZER;
#define DATA_LOCK do{pthread_mutex_lock(&data_mutex);} while (0)
#define DATA_UNLOCK do{pthread_mutex_unlock(&data_mutex);} while (0)
void get_ip_net();
//void * TestIp(void *args); 一直以为线程函数是这种空指针函数,其实任何函数都可以,该例子用了整型函数一样可以获取正确结果
int TestIp(void *args);
void sort_ip_asc();
int main(int argc, char **argv) {
time_t ts,tf;
ts=time(NULL);
int ret=0;
int i;
char test_ip[64] = {0};
pthread_t pid[255];
get_ip_net();
if (strlen(ip_net)<6)
exit(-1);
for (i=2;i<255;i++)
{
memset(test_ip, 0, 64);
sprintf(test_ip,"%s%d",ip_net,i);
//if ((ret=pthread_create(&pid[i], NULL, (void *)TestIp, (void *)strdup(test_ip))) !=0)
if ((ret=pthread_create(&pid[i], NULL, (void *)&TestIp, (void *)strdup(test_ip))) !=0)
{
printf("create pthread failed, pid NO. is %d;error NO. is %d.\n", i, ret);
}
}
for (i=2;i<255;i++)
{
pthread_join(pid[i], NULL);
}
printf("This local net has %d useful ip:\n",useful_ip_count);
sort_ip_asc();
for (i=0;i< useful_ip_count;i++)
{
printf(" %d: %s\n", i, useful_ip[i]);
}
for (i=0;i< useful_ip_count;i++)
{
if(useful_ip[i] != NULL)
free(useful_ip[i]);
}
tf=time(NULL);
printf("Time cost:%d second\n",(int)(tf-ts));
return 0;
}
void get_ip_net(){
char tmp[256] = {0};
char *p = NULL;
strcpy(tmp,"route -n |grep UG |awk '{print $8}'|xargs ifconfig |grep \"inet addr:\" |awk '{print $2}' |awk -F: '{print $2}' >/root/ip.dat");
if(strlen(tmp)>0 && !system(tmp)) {
FILE *Fp = fopen("/root/ip.dat","r");
if (Fp != NULL)
{
fgets(ip_net, 127, Fp);
fclose(Fp);
p=strrchr(ip_net, '.');
if (p != NULL)
*(p+1)='\0';
}
}
}
//void *TestIp(void *args) {
// char tmp[128] = {0};
// char *ip = NULL;
//
// ip = (char *)args;
// sprintf(tmp,"ping -c 2 %s >/dev/null 2>&1", ip);
// if (!system(tmp))
// {
// DATA_LOCK;
// useful_ip[useful_ip_count] = strdup(ip);
// useful_ip_count++;
// DATA_UNLOCK;
// }
//
// if(ip != NULL)
// free(ip);
//
// return NULL;
//}
int TestIp(void *args) {
char tmp[128] = {0};
char *ip = NULL;
ip = (char *)args;
sprintf(tmp,"ping -c 2 %s >/dev/null 2>&1", ip);
if (!system(tmp))
{
DATA_LOCK;
useful_ip[useful_ip_count] = strdup(ip);
useful_ip_count++;
DATA_UNLOCK;
}
if(ip != NULL)
free(ip);
return 0;
}
void sort_ip_asc(){
int i, j, lastSwap;
int p1,p2;
char *tmp = NULL;
char *p = NULL;
for (j=useful_ip_count-1; j>0; j=lastSwap) {
lastSwap=0; //每一轮要初始化为0,防止某一轮未发生交换,lastSwap保留上一轮的值进入死循环
for (i=0; i<j; i++) {//get a max number one for loop
if (useful_ip[i] == NULL || useful_ip[i+1] == NULL)
break;
p=strrchr(useful_ip[i], '.');
p1=atoi(p+1);
p=strrchr(useful_ip[i+1], '.');
p2=atoi(p+1);
if (p1 > p2) {
tmp = useful_ip[i];
useful_ip[i] = useful_ip[i+1];
useful_ip[i+1] =tmp;
//最后一次交换位置的坐标
lastSwap = i;
}
}
}
}
编译:gcc -g a.c -lpthread -o a -Wall
执行结果:
[root~]# ./a
This local net has 22 useful ip:
0: 192.168.1.12
1: 192.168.1.50
2: 192.168.1.99
3: 192.168.1.100
4: 192.168.1.104
5: 192.168.1.112
6: 192.168.1.113
7: 192.168.1.114
8: 192.168.1.117
9: 192.168.1.128
10: 192.168.1.132
11: 192.168.1.150
12: 192.168.1.155
13: 192.168.1.156
14: 192.168.1.188
15: 192.168.1.191
16: 192.168.1.192
17: 192.168.1.198
18: 192.168.1.203
19: 192.168.1.216
20: 192.168.1.250
21: 192.168.1.254
Time cost:11 second