1

我在 C++ 中有这个简单的线程创建程序,在全局声明 RW 锁期间,程序按预期执行,但是当在本地(即在函数内部)进行相同的锁声明时,只有一个线程执行,另一个线程挂起。

在职的:

#include <iostream>
#include <pthread.h>

using namespace std;
int i = 0;
**pthread_rwlock_t mylock;** //GLOBAL

void* IncrementCounter(void *dummy)
{
   cout << "Thread ID  " << pthread_self() << endl;
   int cnt = 1;
   while (cnt < 50)
   {
      pthread_rwlock_wrlock(&mylock);
       ++i;
      pthread_rwlock_unlock(&mylock);
      ++cnt;
   cout << "Thread ID ( " << pthread_self() << " ) Incremented Value : " << i << endl;
   }

}
int main()
{
      pthread_t thread1,thread2;
      int ret, ret1;
      ret = pthread_create(&thread1,NULL,IncrementCounter,NULL);
      ret1 = pthread_create(&thread2,NULL,IncrementCounter,NULL);
      pthread_join(thread1,NULL);
      pthread_join(thread2,NULL);

}

*不工作: *

#include <iostream>
#include <pthread.h>

using namespace std;
int i = 0;

void* IncrementCounter(void *dummy)
{
   cout << "Thread ID  " << pthread_self() << endl;
   int cnt = 1;
   **pthread_rwlock_t mylock;** //LOCAL
   while (cnt < 50)
   {
      pthread_rwlock_wrlock(&mylock);
       ++i;
      pthread_rwlock_unlock(&mylock);
      ++cnt;
   cout << "Thread ID ( " << pthread_self() << " ) Incremented Value : " << i << endl;
   }

}
int main()
{
      pthread_t thread1,thread2;
      int ret, ret1;
      ret = pthread_create(&thread1,NULL,IncrementCounter,NULL);
      ret1 = pthread_create(&thread2,NULL,IncrementCounter,NULL);
      pthread_join(thread1,NULL);
      pthread_join(thread2,NULL);

}

这可能是什么原因?

4

3 回答 3

5

In neither case are you correctly initialising the mylock variable - you are just getting "lucky" in the first case. The correct initialisation in the global case would be:

pthread_rwlock_t mylock = PTHREAD_RWLOCK_INITIALIZER;

In the local case, if you want your threads to be accessing the same lock, then it has to be declared static:

static pthread_rwlock_t mylock = PTHREAD_RWLOCK_INITIALIZER;

That's what you want in this case, because you're protecting access to the global i. The lock should be associated with the data, so if i is global then really it makes sense for mylock to be global also.


If you really wanted non-static locks (which in this case, you don't), you would use:

pthread_rwlock_t mylock;

pthread_rwlock_init(&mylock, NULL);

followed by:

pthread_rwlock_destroy(&mylock);

at the end of the function.

于 2012-08-02T06:36:31.487 回答
2

除了其他答案所说的之外,请考虑在 C 和 C++ 中,所有具有静态存储的变量(例如mylock在您的第一个示例中)都被初始化为零。简化,pthread_rwlock_t是一个struct

在您的第一个示例中,mylock具有静态存储持续时间,因此其所有内部成员都初始化为零。碰巧,这相当于 的“解锁”状态pthread_rwlock_t,因为另一个答案中提到的宏PTHREAD_RWLOCK_INITIALIZER将所有内容都初始化为零;在nptl/sysdeps/pthread/pthread.h你可以找到:

#define PTHREAD_RWLOCK_INITIALIZER \
 { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }  

因此,您的第一个示例的所有运行都将始终表现出相同的行为(即锁将开始解锁)。

在您的第二个示例中,mylock未初始化,因为它具有自动存储持续时间。然后,该行为将取决于碰巧位于未初始化内存区域的其他值。大多数时候,锁以“锁定”状态开始,但是,如果你足够幸运(不幸),它会开始解锁。

于 2012-08-02T06:59:57.950 回答
1

The reason is quite clear, you even say so yourself... In the working version the variable is global, while in the non-working the variable is local.

A local variable is only known inside the function, during that call. So if a function is called twice then the variable is unique on both these calls.

If you want to use a local variable, you can mark it static, as that makes it "static" between all invocations of the function.

I suggest you read more about variable scoping and lifetime.

于 2012-08-02T06:37:07.680 回答