#include <iostream>
#include <pthread.h>
#include <unistd.h>
#define NUM 5
int main()
{
pthread_t t1,t2;
void *print_msg(void* );
pthread_create(&t1,NULL,print_msg,(void* )"hello\n");
pthread_create(&t2,NULL,print_msg,(void* )"world\n");
pthread_join(t1,NULL);
pthread_join(t2,NULL);
}
void* print_msg(void* m)
{
char* cp = (char* )m;
int i;
for(i=0;i<NUM;i++)
{
printf("%s",m);
fflush(stdout);
sleep(1);
}
return NULL;
}
首先程序中定义了pthread_t类型的两个变量t1和t2
在pthread_create中第一个参数是线程的地址,第二个参数是指向线程属性的指针,第三个参数是要执行的函数名称,第四个参数是指向要传递给函数的参数的指针。
pthread_join等待线程执行返回,第一个参数是要等待的线程,第二个参数是一个指向返回值的指针,若参数为NULL,则返回值不被考虑。
pthread_join 使得调用线程挂起知道thread参数指定的线程终止,如果第二个参数不是NULL,则线程的返回值存储在第二个参数的变量中。
线程间的通信:
多个线程在一个单独的进程中运行,共享全局变量。因此线程间的通信可以通过设置和读取这些全局变量来进行
例子:
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#define NUM 5
int counter = 0;
int main()
{
pthread_t t1;
void *print_count(void* );
int i;
pthread_create(&t1,NULL,print_count,NULL);
for(i=0;i<NUM;i++)
{
counter++;
sleep(1);
}
pthread_join(t1,NULL);
}
void *print_count(void* )
{
int i;
for(i=0;i<NUM;++i)
{
printf("count=%d\n",counter);
sleep(1);
}
return NULL;
}
主线程和子线程通过共享全局变量counter进行通信
设计一个多线程程序来计数并打印两个文件中的所有字符数
#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;
int total_words;
pthread_mutex_t Counter_lock = PTHREAD_MUTEX_INITIALIZER;
int main(int argc,char* argv[])
{
pthread_t t1,t2;
void *count_words(void* );
if(argc!=3)
{
cout<<"error!"<<endl;
exit(1);
}
total_words = 0;
pthread_create(&t1,NULL,count_words,(void* )argv[1]);
pthread_create(&t2,NULL,count_words,(void* )argv[2]);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
cout<<"total words: "<<total_words<<endl;
}
void *count_words(void* f)
{
char* filename = (char* )f;
FILE* fp;
char c;
if((fp=fopen(filename,"r"))!=NULL)
{
while((c=getc(fp))!=EOF)
{
pthread_mutex_lock(&Counter_lock);
total_words++;
pthread_mutex_unlock(&Counter_lock);
}
}
fclose(fp);
return NULL;
}
首先多个线程对同一个计数器进行操作时会出现问题,所以这里加上了一个互斥锁的变量Counter_lock
通过pthread_mutex_lock(pthread_mutex_t*)和pthread_mutex_unlock(pthread_mutex_t*)在临界区之前之后进行加锁和解锁操作
如果一个线程企图对一个以及锁住的互斥量加锁呢?
那这个线程会阻塞直到互斥量可用于加锁
不足的是使用互斥锁会让程序效率低下
线程和进程的不同:
进程有其独立的数据空间,文件描述符和进程ID
而线程共享一个数据空间,文件描述符和进程ID
例如:一个线程可以new一块空间,而另一个线程可以delete这个空间
对于共享的文件描述符:
在fork调用之后,子进程得到一套新的文件描述符,在子进程关闭这个文件描述符后,对父进程而言依旧是打开的
在多线程程序中,如果将同一个文件描述符传递给两个不同的线程,那么传递给它们的两个值指向同一个文件描述符。如果一个线程中的函数关闭了这个文件,那么次文件描述符对任何线程来说就都关闭了。
exec :如果一个线程调用了exec,系统内核用一个新的程序取代当前的程序从而所有正在运行对线程都将会消失。如果一个线程执行了exit,那么整个进程都将结束运行。所以要是线程的运行导致了内存段异常或者系统错误或是线程崩溃,瘫痪的是整个进程。
如果线程中的某函数调用了fork(),那么只是调用fork()的线程在新的进程中运行