gpt4 book ai didi

c++ - 递归互斥锁背后的想法

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:04:15 27 4
gpt4 key购买 nike

我在学校实验室工作,我们被指示为计数程序创建递归互斥锁。我写了一些代码(不起作用),但我认为这主要是因为我不理解使用递归互斥锁背后的真正想法。谁能详细说明递归互斥锁应该做什么/看起来像什么?

一般说明:我不是要答案,只是要澄清递归互斥锁应该做什么。

此外,如果有人对此感到好奇,请查看此处所需的代码。我正在编辑/实现的代码是 recmutex.c。

recmutex.h

#include <pthread.h>

/*
* The recursive_mutex structure.
*/

struct recursive_mutex {

pthread_cond_t cond;
pthread_mutex_t mutex; //a non-recursive pthread mutex
pthread_t owner;
unsigned int count;
unsigned int wait_count;
};

typedef struct recursive_mutex recursive_mutex_t;


/* Initialize the recursive mutex object.
*Return a non-zero integer if errors occur.
*/

int recursive_mutex_init (recursive_mutex_t *mu);


/* Destroy the recursive mutex object.
*Return a non-zero integer if errors occur.
*/

int recursive_mutex_destroy (recursive_mutex_t *mu);


/* The recursive mutex object referenced by mu shall be
locked by calling pthread_mutex_lock(). When a thread
successfully acquires a mutex for the first time,
the lock count shall be set to one and successfully return.
Every time a thread relocks this mutex, the lock count
shall be incremented by one and return success immediately.
And any other calling thread can only wait on the conditional
variable until being waked up. Return a non-zero integer if errors occur.
*/
int recursive_mutex_lock (recursive_mutex_t *mu);


/* The recursive_mutex_unlock() function shall release the
recursive mutex object referenced by mu. Each time the owner
thread unlocks the mutex, the lock count shall be decremented by one.
When the lock count reaches zero, the mutex shall become available
for other threads to acquire. If a thread attempts to unlock a
mutex that it has not locked or a mutex which is unlocked,
an error shall be returned. Return a non-zero integer if errors occur.
*/

int recursive_mutex_unlock (recursive_mutex_t *mu);

recmutex.c:包含递归互斥体的函数

#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include "recmutex.h"

int recursive_mutex_init (recursive_mutex_t *mu){
int err;
err = pthread_mutex_init(&mu->mutex, NULL);
if(err != 0){
perror("pthread_mutex_init");
return -1;
}else{
return 0;
}
return 0;
}

int recursive_mutex_destroy (recursive_mutex_t *mu){
int err;
err = pthread_mutex_destroy(&mu->mutex);
if(err != 0){
perror("pthread_mutex_destroy");
return -1;
}else{
return 1;
}
return 0;
}

int recursive_mutex_lock (recursive_mutex_t *mu){

if(mutex_lock_count == 0){
pthread_mutex_lock(&mu->mutex);
mu->count++;
mu->owner = pthread_self();
printf("%s", mu->owner);
return 0;
}else if(mutex_lock_count > 0){
pthread_mutex_lock(&mu->mutex);
mu->count++;
mu->owner = pthread_self();
return 0;
}else{
perror("Counter decremented incorrectly");
return -1;
}
}

int recursive_mutex_unlock (recursive_mutex_t *mu){

if(mutex_lock_count <= 0){
printf("Nothing to unlock");
return -1;
}else{
mutex_lock_count--;
pthread_mutex_unlock(&mu->mutex);
return 0;
}
}

count_recursive.cc:上面提到的计数程序。使用 recmutex 函数。

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include "recmutex.h"

//argument structure for the thread
typedef struct _arg_{
int n1;
int n2;
int ntimes;
}Arg;

int count; //global counter
recursive_mutex_t mutex; //the recursive mutex

void do_inc(int n){
int ret;
if(n == 0){
return;
}else{
int c;
ret = recursive_mutex_lock(&mutex);
assert(ret == 0);
c = count;
c = c + 1;
count = c;
do_inc(n - 1);
ret = recursive_mutex_unlock(&mutex);
assert(ret == 0);
}
}

/* Counter increment function. It will increase the counter by n1 * n2 * ntimes. */
void inc(void *arg){
Arg * a = (Arg *)arg;
for(int i = 0; i < a->n1; i++){
for(int j = 0; j < a->n2; j++){
do_inc(a->ntimes);
}
}
}

int isPositiveInteger (const char * s)
{
if (s == NULL || *s == '\0' || isspace(*s))
return 0;
char * p;
int ret = strtol (s, &p, 10);
if(*p == '\0' && ret > 0)
return 1;
else
return 0;
}

int test1(char **argv){

printf("==========================Test 1===========================\n");
int ret;
//Get the arguments from the command line.
int num_threads = atoi(argv[1]); //The number of threads to be created.
int n1 = atoi(argv[2]); //The outer loop count of the inc function.
int n2 = atoi(argv[3]); //The inner loop count of the inc function.
int ntimes = atoi(argv[4]); //The number of increments to be performed in the do_inc function.

pthread_t *th_pool = new pthread_t[num_threads];
pthread_attr_t attr;
pthread_attr_init( &attr );
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);

ret = recursive_mutex_init(&mutex);
assert(ret == 0);

printf("Start Test. Final count should be %d\n", num_threads * n1 * n2 * ntimes );

// Create threads
for(int i = 0; i < num_threads; i++){
Arg *arg = (Arg *)malloc(sizeof(Arg));
arg->n1 = n1;
arg->n2 = n2;
arg->ntimes = ntimes;
ret = pthread_create(&(th_pool[i]), &attr, (void * (*)(void *)) inc, (void *)arg);
assert(ret == 0);
}

// Wait until threads are done
for(int i = 0; i < num_threads; i++){
ret = pthread_join(th_pool[i], NULL);
assert(ret == 0);
}

if ( count != num_threads * n1 * n2 * ntimes) {
printf("\n****** Error. Final count is %d\n", count );
printf("****** It should be %d\n", num_threads * n1 * n2 * ntimes );
}
else {
printf("\n>>>>>> O.K. Final count is %d\n", count );
}

ret = recursive_mutex_destroy(&mutex);
assert(ret == 0);

delete [] th_pool;
return 0;
}


int foo(){
int ret;
printf("Function foo\n");
ret = recursive_mutex_unlock(&mutex);
assert(ret != 0);
return ret;
}

//test a thread call unlock without actually holding it.
int test2(){
int ret;
printf("\n==========================Test 2==========================\n");
pthread_t th;
pthread_attr_t attr;
pthread_attr_init( &attr );
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);

ret = recursive_mutex_init(&mutex);
ret = pthread_create(&th, &attr, (void * (*)(void *))foo, NULL);

printf("Waiting for thread to finish\n");
ret = pthread_join(th, NULL);
assert(ret == 0);
return 0;
}


int main( int argc, char ** argv )
{
int ret;
count = 0;

if( argc != 5 ) {
printf("You must enter 4 arguments. \nUsage: ./count_recursive num_threads n1 n2 ntimes\n");
return -1;
}

if(isPositiveInteger(argv[1]) != 1 || isPositiveInteger(argv[2]) != 1 || isPositiveInteger(argv[3]) != 1 || isPositiveInteger(argv[4]) != 1 ){
printf("All the 4 arguments must be positive integers\n");
return -1;
}

test1(argv);

test2();

return 0;
}

最佳答案

递归互斥锁的思想是它可以被当前持有锁的线程成功地重新锁定。例如:

如果我有这样的互斥体(这是伪代码):

mutex l;
recursive_mutex r;

如果我这样做,在一个线程中:

l.lock();
l.lock(); // this would hang the thread.

但是

r.lock();
r.lock();
r.lock(); // this would all pass though with no issue.

在实现递归互斥锁时,您需要检查锁定它的线程 ID,如果它被锁定,如果它与当前线程 ID 匹配,则返回成功。

关于c++ - 递归互斥锁背后的想法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22640641/

27 4 0