互斥信号量is互斥量by short
互斥量的类型
/**********/usr/include/pthread.h**********
Mutex types.
*/
enum
{
PTHREAD_MUTEX_TIMED_NP,
PTHREAD_MUTEX_RECURSIVE_NP,
PTHREAD_MUTEX_ERRORCHECK_NP,
PTHREAD_MUTEX_ADAPTIVE_NP
#if defined __USE_UNIX98 || defined __USE_XOPEN2K8
,
PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP,
PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
#endif
#ifdef __USE_GNU
/* For compatibility. */
, PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP
#endif
};
/*
/usr/include/bits/pthreadtype.h********
pthread_mutex_t
*/
typedef union
{
struct
{
int __lock;
unsigned int __nr_readers;
unsigned int __readers_wakeup;
unsigned int __writer_wakeup;
unsigned int __nr_readers_queued;
unsigned int __nr_writers_queued;
/* FLAGS must stay at this position in the structure to maintain
binary compatibility. */
unsigned char __flags;
unsigned char __shared;
unsigned char __pad1;
unsigned char __pad2;
int __writer;
} __data;
char __size[__SIZEOF_PTHREAD_RWLOCK_T];
long int __align;
} pthread_rwlock_t;
*PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁。
当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。
*PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,
允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。
*PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,
如果同一个线程请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同。
这样就保证当步允许多次加锁 时不会出现最简单情况下的死锁。
*PTHREAD_MUTEX_ADAPTIVE_NP,适应锁,
动作最简单的锁类型,仅等待解锁后重新竞争。
a线程可解b线程的普通锁,如下
[root@localhost ch12]# cat thread4.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
void *thread_function(void *arg);
pthread_mutex_t work_mutex; /* protects both work_area and time_to_exit */
pthread_mutexattr_t attr;
#define WORK_SIZE 1024
char work_area[WORK_SIZE];
int main() {
int res;
pthread_t a_thread;
void *thread_result;
if((res=pthread_mutexattr_init(&attr))!=0)
perror("pthread_mutexattr_init error");
if((res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_NORMAL))!=0)
perror("pthread_mutexattr_settype error");
if((res= pthread_mutex_init(&work_mutex, &attr))!=0)
perror("pthread_mutexattr_init error");
res = pthread_create(&a_thread, NULL, thread_function, NULL);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
//lock
printf("work_mutex in main_1:%d\n",work_mutex);
res=pthread_mutex_lock(&work_mutex);
printf("main1res_1:%d\n",res);
printf("work_mutex in main_2:%d\n",work_mutex);
printf("------------Waiting for thread to finish------------\n");
res = pthread_join(a_thread, &thread_result);
if (res != 0) {
perror("Thread join failed");
exit(EXIT_FAILURE);
}
printf("Thread joined\n");
pthread_mutex_destroy(&work_mutex);
printf("sleep(120)\n");
sleep(120);
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg)
{
int res;
printf("hello_1\n");
printf("work_mutex in sub_1:%d\n",work_mutex);
res=pthread_mutex_unlock(&work_mutex);
printf("subres_1:%d\n",res);
printf("work_mutex in sub_2:%d\n",work_mutex);
printf("hello_2\n");
}
[root@localhost ch12]# make
cc -D_REENTRANT -lpthread thread4.c -o thread4
[root@localhost ch12]# ./thread4
work_mutex in main_1:0
main1res_1:0
work_mutex in main_2:1
------------Waiting for thread to finish------------
hello_1
work_mutex in sub_1:1
subres_1:0
work_mutex in sub_2:0
hello_2
Thread joined
sleep(120)
上面的printf("%d\n",work_mutex); 打印结果是当前work_mutex的上锁次数,普通锁此值最大为1
子线程解对主线程的锁,返回值0,说明成功解锁,执行结果也验证le这一点
已经知道,b线程欲对a线程已经上过的普通锁进行上锁,则b线程会被阻塞
a线程本身对普通锁多次上锁的的话,会怎么样呢
[root@localhost ch12]# cat thread4.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
void *thread_function(void *arg);
pthread_mutex_t work_mutex; /* protects both work_area and time_to_exit */
pthread_mutexattr_t attr;
#define WORK_SIZE 1024
char work_area[WORK_SIZE];
int main() {
int res;
pthread_t a_thread;
void *thread_result;
if((res=pthread_mutexattr_init(&attr))!=0)
perror("pthread_mutexattr_init error");
if((res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_NORMAL))!=0)//mutex type
perror("pthread_mutexattr_settype error");
if((res= pthread_mutex_init(&work_mutex, &attr))!=0)
perror("pthread_mutexattr_init error");
res = pthread_create(&a_thread, NULL, thread_function, NULL);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
//lock
printf("work_mutex in main_1:%d\n",work_mutex);
res=pthread_mutex_lock(&work_mutex);
printf("main1res_1:%d\n",res);
printf("work_mutex in main_2:%d\n",work_mutex);
//lock again
res=pthread_mutex_lock(&work_mutex);
printf("main1res_1:%d\n",res);
printf("work_mutex in main_2:%d\n",work_mutex);
printf("------------Waiting for thread to finish------------\n");
res = pthread_join(a_thread, &thread_result);
if (res != 0) {
perror("Thread join failed");
exit(EXIT_FAILURE);
}
printf("Thread joined\n");
pthread_mutex_destroy(&work_mutex);
printf("sleep(120)\n");
sleep(120);
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg)
{
/* int res;
printf("hello_1\n");
printf("work_mutex in sub_1:%d\n",work_mutex);
res=pthread_mutex_unlock(&work_mutex);
printf("subres_1:%d\n",res);
printf("work_mutex in sub_2:%d\n",work_mutex);
printf("hello_2\n");
*/}
[root@localhost ch12]# ./thread4
work_mutex in main_1:0
main1res_1:0
work_mutex in main_2:1
结果是形成死锁------须在第二次上锁之前先解锁
可以自己解,也可以其他线程解
看来普通锁面对本线程or其他线程,都是一个态度
将上面的普通锁换成检错锁,即line22改为
if((res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_ERRORCHECK))!=0)//mutex type
结果是,
第二次上锁时没被阻塞,而是返回一个35的错误代码
[root@localhost ch12]# ./thread4
work_mutex in main_1:0
main1res_1:0
work_mutex in main_2:1
main1res_1:35
work_mutex in main_2:1
------------Waiting for thread to finish------------
Thread joined
sleep(120)
将上面的普通锁换成嵌套锁,即line22改为RECURSIVE,并修改程序如下
[root@localhost ch12]# cat thread4.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
void *thread_function(void *arg);
pthread_mutex_t work_mutex; /* protects both work_area and time_to_exit */
pthread_mutexattr_t attr;
#define WORK_SIZE 1024
char work_area[WORK_SIZE];
int main() {
int res;
pthread_t a_thread;
void *thread_result;
if((res=pthread_mutexattr_init(&attr))!=0)
perror("pthread_mutexattr_init error");
if((res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE))!=0)//mutex type
perror("pthread_mutexattr_settype error");
if((res= pthread_mutex_init(&work_mutex, &attr))!=0)
perror("pthread_mutexattr_init error");
res = pthread_create(&a_thread, NULL, thread_function, NULL);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
//lock
printf("work_mutex in main_1:%d\n",work_mutex);
res=pthread_mutex_lock(&work_mutex);
printf("main1res_1:%d\n",res);
printf("work_mutex in main_2:%d\n",work_mutex);
//lock again
res=pthread_mutex_lock(&work_mutex);
printf("main1res_1:%d\n",res);
printf("work_mutex in main_2:%d\n",work_mutex);
printf("------------Waiting for thread to finish------------\n");
res = pthread_join(a_thread, &thread_result);
if (res != 0) {
perror("Thread join failed");
exit(EXIT_FAILURE);
}
printf("Thread joined\n");
pthread_mutex_destroy(&work_mutex);
printf("sleep(120)\n");
sleep(120);
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg)
{
int res;
printf("hello_1\n");
printf("work_mutex in sub_1:%d\n",work_mutex);
res=pthread_mutex_lock(&work_mutex);
printf("subres_1:%d\n",res);
printf("work_mutex in sub_2:%d\n",work_mutex);
printf("hello_2\n");
}
[root@localhost ch12]# ./thread4
work_mutex in main_1:0
main1res_1:0
work_mutex in main_2:1
main1res_1:0
work_mutex in main_2:1
------------Waiting for thread to finish------------
hello_1
work_mutex in sub_1:1
可见主线程中在解锁之前多次加锁均不会阻塞,但在子线程中加锁却被阻塞
另外,
子线程解不开主线程上的锁
主线程加了几次锁,就要释放几次锁,否则子线程永远得不到此锁而一直阻塞
貌似嵌套锁就是用来帮第一个上锁者占茅坑的
本来认为printf("%d\n",work_mutex); 打印结果是当前work_mutex的上锁次数
但是即使是用嵌套锁试验,只是偶尔可以打印出2
不知为何,先放着哈。
从以上也可看出,sleep是用来阻塞的并且阻塞的是当前线程,不是进程
apue2中列出了各种情况下操作锁的反应,不过有些结果与我试验de不一致