sem_post(&mutex); sleep(1); } } 下面是posix基于内存的信号灯实现各进程间的互斥。但要注意它并不能得到我们想要的结果。
#include #include #include #include void print(pid_t); sem_t *sem; /*定义Posix有名信号灯*/ int val; /*定义信号灯当前值*/ int main(int argc,char *argv[]) { int n=0; sem=sem_init(sem,0,3); /*打开一个信号灯*/ sem_getvalue(sem,&val); /*查看信号灯的值*/ printf(“The value have %d\\n”,val); while(n++<5) /*循环创建5个子进程,使它们同步运行*/ { if(fork()==0) { sem_wait(sem); /*申请信号灯*/ print(getpid()); /*调用共享代码段*/ sleep(1); sem_post(sem); /*释放信号灯*/ printf(“I’m finished,my pid is %d\\n”,getpid()); return 0; } wait(); /*等待所有子进程结束*/ return 0; } void print(pid_t pid) { printf(“I get it,my pid is %d\\n”,pid); sem_getvalue(sem,&val); printf(“Now the value have %d\\n”,val); } 下面是运行结果:
#cc –lpthread –o sem sem.c #./sem
The value have 3
I get it,my pid is 2236 Now the value have 2 I get it,my pid is 2237 Now the value have 2
I get it,my pid is 2238 Now the value have 2 I get it,my pid is 2239 Now the value have 2 Iget it,my pid is 2240 Now the value have 2 I’m finished,my pid is 2236 I’m finished,my pid is 2237 I’m finished,my pid is 2238 I’m finished,my pid is 2239 I’m finished,my pid is 2240
问题在于sem信号灯不在共享内存区中。fork出来的子进程通常不共享父进程的内存空间。子进程是在父进程内存空间的拷贝上启动的,它跟共享内存不是一回事。
第四章 互斥量
一、什么是互斥锁
另一种在多线程程序中同步访问手段是使用互斥量。程序员给某个对象加上一把“锁”,每次只允许一个线程去访问它。如果想对代码关键部分的访问进行控制,你必须在进入这段代码之前锁定一把互斥量,在完成操作之后再打开它。
互斥量函数有
pthread_mutex_init 初始化一个互斥量 pthread_mutex_lock 给一个互斥量加锁
pthread_mutex_trylock 加锁,如果失败不阻塞 pthread_mutex_unlock 解锁
可以通过使用pthread的互斥接口保护数据,确保同一时间只有一个线程访问数据。互斥量从本质上说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁。对互斥量进行加锁以后,任何其他试图再次对互斥量加锁的线程将会被阻塞直到当前线程释放该互斥锁。如果释放互斥锁时有多个线程阻塞,所以在该互斥锁上的阻塞线程都会变成可进行状态,第一个变成运行状态的线程可以对互斥量加锁,其他线程在次被阻塞,等待下次运行状态。
互斥量用pthread_mutex_t数据类型来表示,在使用互斥量以前,必须首先对它进行初始化,可以把它置为常量PTHREAD_MUTEX_INITIALIZER(只对静态分配的互斥量),也可以通过调用pthread_mutex_init函数进行初始化,如果动态地分配互斥量,那么释放内存前需要调用pthread_mutex_destroy.
二、初始化/回收互斥锁 1. 名称:: pthread_mutex_init 功能: 初始化互斥锁。 头文件: #include 函数原形: int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutex_t *attr); 参数: mutex 互斥量 attr 互斥锁属性 返回值: 若成功则返回0,否则返回错误编号。 mutex是我们要锁住的互斥量,attr是互斥锁的属性,可用相应的函数修改,我们在下章介绍,要用默认的属性初始化互斥量,只需把attr设置为NULL。
2. 名称:: pthread_mutex_destroy 功能: 释放对互斥变量分配的资源 头文件: #include 函数原形: int pthread_mutex_destroy(pthread_mutex_t *mutex); 参数: 返回值: 若成功则返回0,否则返回错误编号。
三、对互斥量加减锁
3. 名称:: 功能: 头文件: 函数原形: 参数: 返回值:
pthread_mutex_lock/ pthread_mutex_trylock/ pthread_mutex_unlock 对互斥量加/减锁 #include int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex); 若成功则返回0,否则返回错误编号。 对互斥量进行加锁,需要调用pthread_mutex_lock,如果互斥量已经上锁,调用线程阻塞直至互斥量解锁。对互斥量解锁,需要调用pthread_mutex_unlock. 如果线程不希望被阻塞,他可以使用pthread_mutex_trylock尝试对互斥量进行加锁。如果调用pthread_mutex_trylock时互斥量处于未锁住状态,那么
pthread_mutex_trylock将锁住互斥量,否则就会失败,不能锁住互斥量,而返回EBUSY。
下面试例子可以证明对互斥量加锁的必要性: 我们先来看不加锁的程序。 #inlcude #include #inlcude #include viid *thread_function(void *arg); int run_now=1; /*用run_now代表共享资源*/ int main() { int print_count1=0; /*用于控制循环*/ prhread_t a_thread; if(pthread_create(&a_thread,NULL,thread_function,NULL)!=0) /*创建一个进程*/ { perror(“Thread createion failed”); exit(1); } while(print_count1++<5) { if(run_now==1) /主线程:如果run_now为1就把它修改为2*/ { printf(“main thread is run\\n”); run_now=2; } else { printf(“main thread is sleep\\n”); sleep(1); } } pthread_join(a_thread,NULL); /*等待子线程结束*/ exit(0); } void *thread_function(void *arg)
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库linux多线程编程(8)在线全文阅读。