Linux pthread_mutex演示程序
C++语言:
Linux pthread_mutex演示程序
Linux
下pthread
中使用mutex
进行互斥的程序和结果
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "pthread.h"
#define THREAD_NUMBER 2
int sum = 0;
void* fun( void* arg) {
int t = (*( int*)arg);
int i;
for (i = t ;i < 10000; i += 2)
sum = sum + i;
return NULL;
}
int main(){
pthread_t T[THREAD_NUMBER];
int arg[THREAD_NUMBER];
int ret,i;
void* join_result;
for (i = 0 ;i < THREAD_NUMBER; ++ i){
arg[i] = i;
ret = pthread_create(&T[i],NULL,fun,( void*)&arg[i]);
if (ret){
printf( "Thread %d crreate failure! \n ",i);
exit(EXIT_FAILURE);
}
}
for (i = 0 ;i < THREAD_NUMBER; ++ i){
ret = pthread_join(T[i],&join_result);
if (ret) {
printf( "Thread %d join failure! \n ",i);
exit(EXIT_FAILURE);
}
}
printf( "sum = %d \n ",sum);
return 0;
}
上面的程序是没有进行互斥的 nomutex.c 该程序用于求 1.. .9999 的和,可以gcc -l pthreacd -o test nomutex.c 编译该程序,
并且可以实验运行结果基本上都是不对的,由于该程序没有应用互斥操作,所以可想而知为什么结果是不对的。
下面的程序就在上面程序的基础上加上了求和时的互斥操作,所以运行结果都是对的。
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "pthread.h"
#define THREAD_NUMBER 2
int sum = 0;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* fun( void* arg) {
int t = (*( int*)arg);
int i;
for (i = t ;i < 10000; i += 2) {
pthread_mutex_lock(&mutex);
sum = sum + i;
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main(){
pthread_t T[THREAD_NUMBER];
int arg[THREAD_NUMBER];
int ret,i;
void* join_result;
for (i = 0 ;i < THREAD_NUMBER; ++ i){
arg[i] = i;
ret = pthread_create(&T[i],NULL,fun,( void*)&arg[i]);
if (ret){
printf( "Thread %d crreate failure! \n ",i);
exit(EXIT_FAILURE);
}
}
for (i = 0 ;i < THREAD_NUMBER; ++ i){
ret = pthread_join(T[i],&join_result);
if (ret) {
printf( "Thread %d join failure! \n ",i);
exit(EXIT_FAILURE);
}
}
printf( "sum = %d \n ",sum);
return 0;
}
用这两个小程序,只是想演示一下linux 下pthread 的互斥操作。可以看到,在多线程环境中,为了保证共享变量的值的正确性,
互斥是非常重要的。
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "pthread.h"
#define THREAD_NUMBER 2
int sum = 0;
void* fun( void* arg) {
int t = (*( int*)arg);
int i;
for (i = t ;i < 10000; i += 2)
sum = sum + i;
return NULL;
}
int main(){
pthread_t T[THREAD_NUMBER];
int arg[THREAD_NUMBER];
int ret,i;
void* join_result;
for (i = 0 ;i < THREAD_NUMBER; ++ i){
arg[i] = i;
ret = pthread_create(&T[i],NULL,fun,( void*)&arg[i]);
if (ret){
printf( "Thread %d crreate failure! \n ",i);
exit(EXIT_FAILURE);
}
}
for (i = 0 ;i < THREAD_NUMBER; ++ i){
ret = pthread_join(T[i],&join_result);
if (ret) {
printf( "Thread %d join failure! \n ",i);
exit(EXIT_FAILURE);
}
}
printf( "sum = %d \n ",sum);
return 0;
}
上面的程序是没有进行互斥的 nomutex.c 该程序用于求 1.. .9999 的和,可以gcc -l pthreacd -o test nomutex.c 编译该程序,
并且可以实验运行结果基本上都是不对的,由于该程序没有应用互斥操作,所以可想而知为什么结果是不对的。
下面的程序就在上面程序的基础上加上了求和时的互斥操作,所以运行结果都是对的。
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "pthread.h"
#define THREAD_NUMBER 2
int sum = 0;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* fun( void* arg) {
int t = (*( int*)arg);
int i;
for (i = t ;i < 10000; i += 2) {
pthread_mutex_lock(&mutex);
sum = sum + i;
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main(){
pthread_t T[THREAD_NUMBER];
int arg[THREAD_NUMBER];
int ret,i;
void* join_result;
for (i = 0 ;i < THREAD_NUMBER; ++ i){
arg[i] = i;
ret = pthread_create(&T[i],NULL,fun,( void*)&arg[i]);
if (ret){
printf( "Thread %d crreate failure! \n ",i);
exit(EXIT_FAILURE);
}
}
for (i = 0 ;i < THREAD_NUMBER; ++ i){
ret = pthread_join(T[i],&join_result);
if (ret) {
printf( "Thread %d join failure! \n ",i);
exit(EXIT_FAILURE);
}
}
printf( "sum = %d \n ",sum);
return 0;
}
用这两个小程序,只是想演示一下linux 下pthread 的互斥操作。可以看到,在多线程环境中,为了保证共享变量的值的正确性,
互斥是非常重要的。
我觉得应该加锁。理由如下: 比如说有多个线程都要读一个文件。 先要open 打开一个文件,得到一个fd 对任一个读线程来说操作如下: 1. lseek(fd..)到适当的位置 2. read(fd..) 虽然以上每一个都是原子操作,可是1,2之间是可以中断的。如果线程一lseek了之后,系统暂时挂起线程1,运行线程二,线程也调用lseek。 内核给每一个进程有一个进程描述结构,在Linux中task_struct,在FreeBSD中是proc,存放每一个进程的信息。(下面以FreeBSD为例,因为linux不太清楚,原理应该是一样的). proc里有一个struct filedesc,这里存放一个进程所有打开的文件的信息。它里面有一个struct file的表,每一个表表示这个进程一个打开文件。struct file里面记录了调用lseek设定的这个文件offset大小,对这个文件的读写都是从这里开始的。也就是说这个offset实际上是进程的各个线程共享的。 如果出现像上面说的那种情况,线程一设定的offset就被线程二给修改了。当线程一再开始运行的时候,读到的数据肯定是错误的。 所以说,为了数据的正确性,多线程读一个文件也应该加锁。 |