《POSIX多线程程序设计》
随意顺序解锁互斥量,不会导致死锁的发生。但在使用“试锁-回退”算法时,应该总以相反的顺序,解锁互斥量。这样有利于,减少线程做回退操作的可能性。
链锁及其使用场景
申请多锁的代码示例: 使用backoff 和 yield_flag 命令行参数来调整,增加发生冲突的可能性。
/************************************************************************* * File Name: backoff.c * Created Time: Thu 30 Nov 2017 05:56:18 PM CST *************************************************************************/ #include <stdio.h> #include <pthread.h> #include <sched.h> #include "../errors/errors.h" #define ITERATIONS 10 pthread_mutex_t mutex[3] = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER }; int backoff = 1; /* Whether to backofff or deadlock*/ int yield_flag = 0; /* 0: no yield, >0: yield, <0: sleep */ void *lock_forward(void *arg) { int i, iterator, backoffs; int status; for(iterator=0; iterator<ITERATIONS; ++iterator) { backoffs=0; for(i=0;i<3;i++) { if(i==0){ status = pthread_mutex_lock(&mutex[i]); if(status !=0) err_abort(status,"First lock"); } else { if(backoff) { status = pthread_mutex_trylock(&mutex[i]); } else status = pthread_mutex_lock(&mutex[i]); if(status == EBUSY) { backoffs++; DPRINTF(( " [forward locker backing off at %d]\n",i)); for(;i>=0;i--) { status = pthread_mutex_unlock(&mutex[i]); if(status != 0) err_abort(status,"backoff"); } } else { if(status != 0) err_abort(status,"Lock mutex"); DPRINTF (("forward locker got %d\n", i)); } } if(yield_flag) { if(yield_flag > 0) sched_yield(); else sleep(1); } } printf( "lock forward got all locks, %d backoffs\n",backoffs); for(i=2;i>=0;i--) { pthread_mutex_unlock(&mutex[i]); } sched_yield(); } return NULL; } void *lock_backward(void *arg) { int i, iterator, backoffs; int status; for(iterator=0; iterator<ITERATIONS; ++iterator) { backoffs=0; for(i=2;i>=0;i--) { if(i==2){ status = pthread_mutex_lock(&mutex[i]); if(status !=0) err_abort(status,"First lock"); } else { if(backoff) { status = pthread_mutex_trylock(&mutex[i]); } else status = pthread_mutex_lock(&mutex[i]); if(status == EBUSY) { backoffs++; DPRINTF(( " [backward locker backing off at %d]\n",i)); for(;i<3;i++) { status = pthread_mutex_unlock(&mutex[i]); if(status != 0) err_abort(status,"backoff"); } } else { if(status != 0) err_abort(status,"Lock mutex"); DPRINTF (("backward locker got %d\n", i)); } } if(yield_flag) { if(yield_flag > 0) sched_yield(); else sleep(1); } } printf( "lock backward got all locks, %d backoffs\n",backoffs); for(i=0;i<=2;i++) { pthread_mutex_unlock(&mutex[i]); } sched_yield(); } return NULL; } int main(int argc, char *argv[] ) { pthread_t forward,backward; int status; if(argc > 1) backoff = atoi(argv[1]); if(argc > 2) yield_flag = atoi(argv[2]); status = pthread_create( &forward,NULL,lock_forward,NULL); if(status != 0) err_abort(status,"create forward"); status = pthread_create( &backward,NULL,lock_backward,NULL); if(status != 0) err_abort(status,"create backward"); pthread_exit(NULL); }