I m using pthread_cond_wait(&cond_t, &mutex);
in my program and I m wondering why this function need as a second parameter a mutex variable.
我使用pthread_cond_wait(&cond_t, &mutex);在我的程序中,我想知道为什么这个函数需要作为第二个参数,一个互斥变量。
Does the pthread_cond_wait()
unlock the mutex at the beggining (beggining of the execution pthread_cond_wait()
) and then locked when it finish (just before leaving pthread_cond_wait()
)?
pthread_cond_wait()是否将互斥锁打开(执行pthread_cond_wait()),然后在结束时锁定(在离开pthread_cond_wait()之前)?
3 个解决方案
#1
29
When the first thread calls pthread_cond_wait(&cond_t, &mutex);
it releases the mutex and it waits till condition cond_t
is signaled as complete and mutex
is available.
当第一个线程调用pthread_cond_wait(&cond_t, &mutex)时;它释放互斥锁,它等待条件cond_t被表示为complete,并且互斥锁可用。
So when pthread_cond_signal
is called in the other thread, it doesn't "wake up" the thread that waits yet. mutex
must be unlocked first, only then there is a chance that first thread will get a lock, which means that "upon successful return of pthread_cond_wait
mutex shall have been locked and shall be owned by the calling thread."
因此,当在另一个线程中调用pthread_cond_signal时,它不会“唤醒”等待的线程。必须首先解锁互斥锁,只有这样,第一个线程才有可能获得一个锁,这意味着“当pthread_cond_wait互斥锁成功返回时,它将被锁定,并由调用线程拥有。”
#2
89
There are many text on the subject of condition variables and their usage, so I'll not bore you with a ton of ugly details. The reason they exist at all is to allow you to notify change in a predicate state. The following are critical in understanding proper use of condition variables and their mutex association:
关于条件变量和它们的用法有很多文本,所以我不会给你带来太多的丑陋细节。它们存在的原因是允许您在谓词状态中通知更改。以下是理解正确使用条件变量及其互斥关联的关键:
-
pthread_cond_wait()
simultaneously unlocks the mutex and begins waiting for the condition variable to be signalled. thus you must always have ownership of the mutex before invoking it.pthread_cond_wait()同时解锁互斥锁,并开始等待条件变量的信号。因此,在调用mutex之前,您必须始终拥有它的所有权。
-
pthread_cond_wait()
returns with the mutex locked, thus you must unlock the mutex to allow its use somewhere else when finished with it. Whether the return happened because the condition variable was signalled or not isn't relevant. You still need to check your predicate regardless to account for potential spurious wakeups.pthread_cond_wait()与互斥锁一起返回,因此您必须打开互斥锁以允许它在完成时在其他地方使用它。返回是否发生,因为条件变量是否有信号,与此无关。您仍然需要检查您的谓词,而不考虑潜在的虚假的wakeups。
-
The purpose of the mutex is not to protect the condition variable; it is to protect the predicate on which the condition variable is being used as a signaling mechanism. This is hands-down the most often misunderstood idiom of pthread condition variables and their mutexes. The condition variable doesn't need mutual exclusion protection; the predicate data does. Think of the predicate as an outside-state which is being monitored by the users of the condition-variable/mutex pair.
互斥对象的目的不是保护条件变量;它是为了保护条件变量被用作信号机制的谓词。这是对pthread条件变量及其互斥的最常被误解的用法。条件变量不需要互斥保护;谓词的数据。将谓词看作由条件变量/互斥对象的用户监视的外部状态。
For example, a trivial yet obviously wrong piece of code to wait for a boolean flag fSet
:
例如,一个简单但明显错误的代码段等待一个布尔标志fSet:
bool fSet = false;
int WaitForTrue()
{
while (!fSet)
{
sleep(n);
}
}
I should be obvious the main problem is the predicate, fSet
, is not protected at all. Many things can go wrong here. Ex: From the time you evaluate the while-conditon until the time you begin waiting (or spinning, or whatever) the value may have changed. If that change notification is somehow missed, you're needlessly waiting.
我应该很明显,主要问题是谓词,fSet,根本不受保护。很多事情都可能出错。从你评估的时候开始,直到你开始等待(或旋转,或者其他什么)的时候,这个值可能已经改变了。如果这个更改通知不知怎么被错过了,那么您就不必要地等待了。
We can change this a little so at least the predicate is protected somehow. Mutual exclusion in both modifying and evaluating the predicate is easily provided with (what else) a mutex.
我们可以稍微改变一下,至少谓词是受保护的。在修改和评估谓词的过程中,互斥对象很容易提供(其他)互斥对象。
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
bool fSet = false;
int WaitForTrue()
{
pthread_mutex_lock(&mtx);
while (!fSet)
sleep(n);
pthread_mutex_unlock(&mtx);
}
Well, that seems simple enough.. Now we never evaluate the predicate without first getting exclusive access to it (by latching the mutex). But this is still a major problem. We latched the mutex, but we never release it until our loop is finished. If everyone else plays by the rules and waits for the mutex lock before evaluation or modification of fSet
, they're never be able to do so until we give up the mutex. The only "someone" that can do that in this case is us.
嗯,这看起来很简单。现在,我们永远不会对谓词进行评估,而不首先获得它的独占访问权(通过关闭互斥锁)。但这仍然是一个主要问题。我们锁住了互斥锁,但是直到我们的循环结束,我们才释放它。如果每个人都遵守规则,在评估或修改fSet之前等待互斥锁,那么在我们放弃互斥锁之前,他们永远不能这样做。在这种情况下唯一能做的就是我们。
So what about adding still more layers to this. Will this work?
那么如何在这上面添加更多的层呢。这工作吗?
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
bool fSet = false;
int WaitForTrue()
{
pthread_mutex_lock(&mtx);
while (!fSet)
{
pthread_mutex_unlock(&mtx);
// XXXXX
sleep(n);
// YYYYY
pthread_mutex_lock(&mtx);
}
pthread_mutex_unlock(&mtx);
}
Well, yes it will "work", but still is not much better. The period between XXXXX
and YYYYY
we don't own the mutex (which is ok, since we're not checking or modifying fSet
anyway). But anytime during that period some other thread can (a) obtain the mutex, (b) modify fSet
, and (c) release the mutex, and we won't know a thing about it until we finish our sleep()
, once-again obtain the mutex lock, and loop around for another check.
嗯,是的,它会“工作”,但还是没有更好。在XXXXX和yyyy之间,我们不拥有互斥锁(这是可以的,因为我们没有检查或修改fSet)。但是在这段时间内,其他线程可以(a)获得互斥锁,(b)修改fSet, (c)释放互斥锁,直到我们完成睡眠(),我们才知道它的事情,再一次获得互斥锁,然后循环再检查一次。
There has to be a better way. Somehow there should be a way that we can release the mutex and begin waiting for some sort of signal that tells us a change in the predicate may have happened. Equally important, when we receive that signal and return to our code, we should already own the lock that grants us access to check the predicate data. This is exactly what a condition-variable is designed to provide.
必须有更好的办法。某种程度上,我们可以释放互斥量并开始等待某种信号告诉我们谓词的变化可能发生了。同样重要的是,当我们接收到这个信号并返回到我们的代码时,我们应该已经拥有允许我们访问谓词数据的锁。这正是一个条件变量的设计目的。
The Condition Variable In Action
条件变量的作用。
Enter the condition-variable + mutex pair. The mutex protects access to changing or checking the predicate, while the condition variable sets up a system of monitoring a change, and more importantly, doing so atomically (as far as you're concerned, anyway) with the predicate mutual exclusion:
输入条件变量+互斥锁。互斥锁保护对谓词的更改或检查的访问,而条件变量设置了一个监视更改的系统,更重要的是,在谓词互斥的情况下,以原子的方式(无论如何)这样做。
int WaitForPredicate()
{
// lock mutex (means:lock access to the predicate)
pthread_mutex_lock(&mtx);
// we can safely check this, since no one else should be
// changing it unless they have the mutex, which they don't
// because we just locked it.
while (!predicate)
{
// predicate not met, so begin waiting for notification
// it has been changed *and* release access to change it
// to anyone wanting to by unlatching the mutex, doing
// both (start waiting and unlatching) atomically
pthread_cond_wait(&cv,&mtx);
// upon arriving here, the above returns with the mutex
// latched (we own it). The predicate *may* be true, and
// we'll be looping around to see if it is, but we can
// safely do so because we own the mutex coming out of
// the cv-wait call.
}
// we still own the mutex here. further, we have assessed the
// predicate is true (thus how we broke the loop).
// take whatever action needed.
// You *must* release the mutex before we leave. Remember, we
// still own it even after the code above.
pthread_mutex_unlock(&mtx);
}
For some other thread to signal the loop above, there are several ways to do it, the two most popular below:
对于其他一些用来表示上面的循环的线程,有几种方法可以做到这一点,下面两个最流行的方法是:
pthread_mutex_lock(&mtx);
TODO: change predicate state here as needed.
pthread_mutex_unlock(&mtx);
pthread_cond_signal(&cv);
Another way...
另一种方式…
pthread_mutex_lock(&mtx);
TODO: change predicate state here as needed.
pthread_cond_signal(&cv);
pthread_mutex_unlock(&mtx);
Each has different intrinsic behavior and I invite you to do some homework on those differences and determine which is more appropriate for specific circumstances. The former provides better program flow at the expense of introducing potentially unwarranted wake-ups. The latter reduces those wake-ups but at the price of less context synergy. Either will work in our sample, and you can experiment with how each affects your waiting loops. Regardless, one thing paramount, and both methods fulfill this mandate:
每个人都有不同的内在行为,我邀请你做一些关于这些差异的家庭作业,并决定哪一种更适合具体情况。前者提供了更好的程序流,但代价是引入了可能没有必要的唤醒。后者减少了人们的清醒,但却以较少的环境协同效应为代价。这两种方法都可以在我们的示例中工作,您可以尝试如何影响您的等待循环。无论如何,有一件事是至高无上的,两种方法都履行了这一使命:
Never change, nor check, the predicate condition unless the mutex is locked. Ever.
除非互斥锁被锁定,否则永远不要更改或检查谓词条件。永远。
Simple Monitor Thread
简单监控线程
This type of operation is common in a monitor thread that acts on a specific predicate condition, which (sans' error checking) typically looks something like this:
这种类型的操作在执行特定谓词条件的监视器线程中是很常见的,这种情况下(sans的错误检查)通常是这样的:
void* monitor_proc(void *pv)
{
// acquire mutex ownership
// (which means we own change-control to the predicate)
pthread_mutex_lock(&mtx);
// heading into monitor loop, we own the predicate mutex
while (true)
{
// safe to check; we own the mutex
while (!predicate)
pthread_cond_wait(&cv, &mtx);
// TODO: the cv has been signalled. our predicate data should include
// data to signal a break-state to exit this loop and finish the proc,
// as well as data that we may check for other processing.
}
// we still own the mutex. remember to release it on exit
pthread_mutex_unlock(&mtx);
return pv;
}
A More Complex Monitor Thread
一个更复杂的监控线程。
Modifying this basic form to account for a notification system that doesn't require you to keep the mutex latched once you've picked up the notification becomes a little more involved, but not by very much. Below is a monitor proc that does not keep the mutex latched during regular processing once we've established we've been served (so to speak).
修改这个基本形式来解释一个通知系统,它不需要你在接收到通知后就保留互斥锁,但这不是非常重要。下面是一个监视器proc,它不会在我们确定我们已经被服务(所以说)的情况下,在常规处理过程中保留互斥锁。
void* monitor_proc(void *pv)
{
// acquire mutex ownership
// (which means we own change-control to the predicate)
pthread_mutex_lock(&mtx);
// heading into monitor loop, we own the predicate mutex
while (true)
{
// check predicate
while (!predicate)
pthread_cond_wait(&cv, &mtx);
// some state that is part of the predicate to
// inform us we're finished
if (break-state)
break;
// TODO: perform latch-required work here.
// unlatch the mutex to do our predicate-independant work.
pthread_mutex_unlock(&mtx);
// TODO: perform no-latch-required work here.
// re-latch mutex prior to heading into wait
pthread_mutex_lock(&mtx);
}
// we still own the mutex. remember to release it on exit
pthread_mutex_unlock(&mtx);
return pv;
}
Where would someone use something like that ? Well, suppose your "predicate" is the "state" of a work queue as well as some flag to tell you to stop looping and exit. Upon receiving the notification that something is "different", you check to see if you should continue executing your loop, and deciding you should continue, pop some data off the queue. Modifying the queue requires the mutex be latched (remember, its "state" is part of our predicate). Once we have popped our data, we have it locally and can process it independent of the queue state, so we release the mutex, do our thing, then require the mutex for the next go-around. There are many ways to code the above concept, including judicious use of pthread_cond_broadcast
, etc. But the basic form is hopefully understandable.
有人会用这样的东西吗?那么,假设您的“谓词”是工作队列的“状态”,以及一些标志,告诉您停止循环和退出。在接收到“不同”的通知后,您将检查是否应该继续执行循环,并决定是否继续执行,从队列中弹出一些数据。修改队列需要使用互斥锁(记住,它的“状态”是我们谓词的一部分)。一旦我们取出数据,我们就在本地拥有它,并且可以独立于队列状态处理它,所以我们释放互斥锁,做我们的事情,然后要求互斥对象进行下一个操作。有很多方法可以对上述概念进行编码,包括明智地使用pthread_cond_broadcast等,但是基本形式是可以理解的。
This turned out to be considerably longer than I had hoped, but this is a major hurdle for people learning pthread-programming, and I feel it is worth the extra time/effort. I hope you got something out of it.
这比我所希望的要长得多,但这是人们学习pthread-programming的一个主要障碍,我觉得这是值得付出额外的时间/努力的。我希望你能从中得到些什么。
#3
5
yes it unlocks, waits for the condition to be fulfilled and then waits till it can reaquire the passed mutex.
是的,它会解锁,等待条件满足,然后等待,直到它可以重新获得通过的互斥锁。
#1
29
When the first thread calls pthread_cond_wait(&cond_t, &mutex);
it releases the mutex and it waits till condition cond_t
is signaled as complete and mutex
is available.
当第一个线程调用pthread_cond_wait(&cond_t, &mutex)时;它释放互斥锁,它等待条件cond_t被表示为complete,并且互斥锁可用。
So when pthread_cond_signal
is called in the other thread, it doesn't "wake up" the thread that waits yet. mutex
must be unlocked first, only then there is a chance that first thread will get a lock, which means that "upon successful return of pthread_cond_wait
mutex shall have been locked and shall be owned by the calling thread."
因此,当在另一个线程中调用pthread_cond_signal时,它不会“唤醒”等待的线程。必须首先解锁互斥锁,只有这样,第一个线程才有可能获得一个锁,这意味着“当pthread_cond_wait互斥锁成功返回时,它将被锁定,并由调用线程拥有。”
#2
89
There are many text on the subject of condition variables and their usage, so I'll not bore you with a ton of ugly details. The reason they exist at all is to allow you to notify change in a predicate state. The following are critical in understanding proper use of condition variables and their mutex association:
关于条件变量和它们的用法有很多文本,所以我不会给你带来太多的丑陋细节。它们存在的原因是允许您在谓词状态中通知更改。以下是理解正确使用条件变量及其互斥关联的关键:
-
pthread_cond_wait()
simultaneously unlocks the mutex and begins waiting for the condition variable to be signalled. thus you must always have ownership of the mutex before invoking it.pthread_cond_wait()同时解锁互斥锁,并开始等待条件变量的信号。因此,在调用mutex之前,您必须始终拥有它的所有权。
-
pthread_cond_wait()
returns with the mutex locked, thus you must unlock the mutex to allow its use somewhere else when finished with it. Whether the return happened because the condition variable was signalled or not isn't relevant. You still need to check your predicate regardless to account for potential spurious wakeups.pthread_cond_wait()与互斥锁一起返回,因此您必须打开互斥锁以允许它在完成时在其他地方使用它。返回是否发生,因为条件变量是否有信号,与此无关。您仍然需要检查您的谓词,而不考虑潜在的虚假的wakeups。
-
The purpose of the mutex is not to protect the condition variable; it is to protect the predicate on which the condition variable is being used as a signaling mechanism. This is hands-down the most often misunderstood idiom of pthread condition variables and their mutexes. The condition variable doesn't need mutual exclusion protection; the predicate data does. Think of the predicate as an outside-state which is being monitored by the users of the condition-variable/mutex pair.
互斥对象的目的不是保护条件变量;它是为了保护条件变量被用作信号机制的谓词。这是对pthread条件变量及其互斥的最常被误解的用法。条件变量不需要互斥保护;谓词的数据。将谓词看作由条件变量/互斥对象的用户监视的外部状态。
For example, a trivial yet obviously wrong piece of code to wait for a boolean flag fSet
:
例如,一个简单但明显错误的代码段等待一个布尔标志fSet:
bool fSet = false;
int WaitForTrue()
{
while (!fSet)
{
sleep(n);
}
}
I should be obvious the main problem is the predicate, fSet
, is not protected at all. Many things can go wrong here. Ex: From the time you evaluate the while-conditon until the time you begin waiting (or spinning, or whatever) the value may have changed. If that change notification is somehow missed, you're needlessly waiting.
我应该很明显,主要问题是谓词,fSet,根本不受保护。很多事情都可能出错。从你评估的时候开始,直到你开始等待(或旋转,或者其他什么)的时候,这个值可能已经改变了。如果这个更改通知不知怎么被错过了,那么您就不必要地等待了。
We can change this a little so at least the predicate is protected somehow. Mutual exclusion in both modifying and evaluating the predicate is easily provided with (what else) a mutex.
我们可以稍微改变一下,至少谓词是受保护的。在修改和评估谓词的过程中,互斥对象很容易提供(其他)互斥对象。
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
bool fSet = false;
int WaitForTrue()
{
pthread_mutex_lock(&mtx);
while (!fSet)
sleep(n);
pthread_mutex_unlock(&mtx);
}
Well, that seems simple enough.. Now we never evaluate the predicate without first getting exclusive access to it (by latching the mutex). But this is still a major problem. We latched the mutex, but we never release it until our loop is finished. If everyone else plays by the rules and waits for the mutex lock before evaluation or modification of fSet
, they're never be able to do so until we give up the mutex. The only "someone" that can do that in this case is us.
嗯,这看起来很简单。现在,我们永远不会对谓词进行评估,而不首先获得它的独占访问权(通过关闭互斥锁)。但这仍然是一个主要问题。我们锁住了互斥锁,但是直到我们的循环结束,我们才释放它。如果每个人都遵守规则,在评估或修改fSet之前等待互斥锁,那么在我们放弃互斥锁之前,他们永远不能这样做。在这种情况下唯一能做的就是我们。
So what about adding still more layers to this. Will this work?
那么如何在这上面添加更多的层呢。这工作吗?
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
bool fSet = false;
int WaitForTrue()
{
pthread_mutex_lock(&mtx);
while (!fSet)
{
pthread_mutex_unlock(&mtx);
// XXXXX
sleep(n);
// YYYYY
pthread_mutex_lock(&mtx);
}
pthread_mutex_unlock(&mtx);
}
Well, yes it will "work", but still is not much better. The period between XXXXX
and YYYYY
we don't own the mutex (which is ok, since we're not checking or modifying fSet
anyway). But anytime during that period some other thread can (a) obtain the mutex, (b) modify fSet
, and (c) release the mutex, and we won't know a thing about it until we finish our sleep()
, once-again obtain the mutex lock, and loop around for another check.
嗯,是的,它会“工作”,但还是没有更好。在XXXXX和yyyy之间,我们不拥有互斥锁(这是可以的,因为我们没有检查或修改fSet)。但是在这段时间内,其他线程可以(a)获得互斥锁,(b)修改fSet, (c)释放互斥锁,直到我们完成睡眠(),我们才知道它的事情,再一次获得互斥锁,然后循环再检查一次。
There has to be a better way. Somehow there should be a way that we can release the mutex and begin waiting for some sort of signal that tells us a change in the predicate may have happened. Equally important, when we receive that signal and return to our code, we should already own the lock that grants us access to check the predicate data. This is exactly what a condition-variable is designed to provide.
必须有更好的办法。某种程度上,我们可以释放互斥量并开始等待某种信号告诉我们谓词的变化可能发生了。同样重要的是,当我们接收到这个信号并返回到我们的代码时,我们应该已经拥有允许我们访问谓词数据的锁。这正是一个条件变量的设计目的。
The Condition Variable In Action
条件变量的作用。
Enter the condition-variable + mutex pair. The mutex protects access to changing or checking the predicate, while the condition variable sets up a system of monitoring a change, and more importantly, doing so atomically (as far as you're concerned, anyway) with the predicate mutual exclusion:
输入条件变量+互斥锁。互斥锁保护对谓词的更改或检查的访问,而条件变量设置了一个监视更改的系统,更重要的是,在谓词互斥的情况下,以原子的方式(无论如何)这样做。
int WaitForPredicate()
{
// lock mutex (means:lock access to the predicate)
pthread_mutex_lock(&mtx);
// we can safely check this, since no one else should be
// changing it unless they have the mutex, which they don't
// because we just locked it.
while (!predicate)
{
// predicate not met, so begin waiting for notification
// it has been changed *and* release access to change it
// to anyone wanting to by unlatching the mutex, doing
// both (start waiting and unlatching) atomically
pthread_cond_wait(&cv,&mtx);
// upon arriving here, the above returns with the mutex
// latched (we own it). The predicate *may* be true, and
// we'll be looping around to see if it is, but we can
// safely do so because we own the mutex coming out of
// the cv-wait call.
}
// we still own the mutex here. further, we have assessed the
// predicate is true (thus how we broke the loop).
// take whatever action needed.
// You *must* release the mutex before we leave. Remember, we
// still own it even after the code above.
pthread_mutex_unlock(&mtx);
}
For some other thread to signal the loop above, there are several ways to do it, the two most popular below:
对于其他一些用来表示上面的循环的线程,有几种方法可以做到这一点,下面两个最流行的方法是:
pthread_mutex_lock(&mtx);
TODO: change predicate state here as needed.
pthread_mutex_unlock(&mtx);
pthread_cond_signal(&cv);
Another way...
另一种方式…
pthread_mutex_lock(&mtx);
TODO: change predicate state here as needed.
pthread_cond_signal(&cv);
pthread_mutex_unlock(&mtx);
Each has different intrinsic behavior and I invite you to do some homework on those differences and determine which is more appropriate for specific circumstances. The former provides better program flow at the expense of introducing potentially unwarranted wake-ups. The latter reduces those wake-ups but at the price of less context synergy. Either will work in our sample, and you can experiment with how each affects your waiting loops. Regardless, one thing paramount, and both methods fulfill this mandate:
每个人都有不同的内在行为,我邀请你做一些关于这些差异的家庭作业,并决定哪一种更适合具体情况。前者提供了更好的程序流,但代价是引入了可能没有必要的唤醒。后者减少了人们的清醒,但却以较少的环境协同效应为代价。这两种方法都可以在我们的示例中工作,您可以尝试如何影响您的等待循环。无论如何,有一件事是至高无上的,两种方法都履行了这一使命:
Never change, nor check, the predicate condition unless the mutex is locked. Ever.
除非互斥锁被锁定,否则永远不要更改或检查谓词条件。永远。
Simple Monitor Thread
简单监控线程
This type of operation is common in a monitor thread that acts on a specific predicate condition, which (sans' error checking) typically looks something like this:
这种类型的操作在执行特定谓词条件的监视器线程中是很常见的,这种情况下(sans的错误检查)通常是这样的:
void* monitor_proc(void *pv)
{
// acquire mutex ownership
// (which means we own change-control to the predicate)
pthread_mutex_lock(&mtx);
// heading into monitor loop, we own the predicate mutex
while (true)
{
// safe to check; we own the mutex
while (!predicate)
pthread_cond_wait(&cv, &mtx);
// TODO: the cv has been signalled. our predicate data should include
// data to signal a break-state to exit this loop and finish the proc,
// as well as data that we may check for other processing.
}
// we still own the mutex. remember to release it on exit
pthread_mutex_unlock(&mtx);
return pv;
}
A More Complex Monitor Thread
一个更复杂的监控线程。
Modifying this basic form to account for a notification system that doesn't require you to keep the mutex latched once you've picked up the notification becomes a little more involved, but not by very much. Below is a monitor proc that does not keep the mutex latched during regular processing once we've established we've been served (so to speak).
修改这个基本形式来解释一个通知系统,它不需要你在接收到通知后就保留互斥锁,但这不是非常重要。下面是一个监视器proc,它不会在我们确定我们已经被服务(所以说)的情况下,在常规处理过程中保留互斥锁。
void* monitor_proc(void *pv)
{
// acquire mutex ownership
// (which means we own change-control to the predicate)
pthread_mutex_lock(&mtx);
// heading into monitor loop, we own the predicate mutex
while (true)
{
// check predicate
while (!predicate)
pthread_cond_wait(&cv, &mtx);
// some state that is part of the predicate to
// inform us we're finished
if (break-state)
break;
// TODO: perform latch-required work here.
// unlatch the mutex to do our predicate-independant work.
pthread_mutex_unlock(&mtx);
// TODO: perform no-latch-required work here.
// re-latch mutex prior to heading into wait
pthread_mutex_lock(&mtx);
}
// we still own the mutex. remember to release it on exit
pthread_mutex_unlock(&mtx);
return pv;
}
Where would someone use something like that ? Well, suppose your "predicate" is the "state" of a work queue as well as some flag to tell you to stop looping and exit. Upon receiving the notification that something is "different", you check to see if you should continue executing your loop, and deciding you should continue, pop some data off the queue. Modifying the queue requires the mutex be latched (remember, its "state" is part of our predicate). Once we have popped our data, we have it locally and can process it independent of the queue state, so we release the mutex, do our thing, then require the mutex for the next go-around. There are many ways to code the above concept, including judicious use of pthread_cond_broadcast
, etc. But the basic form is hopefully understandable.
有人会用这样的东西吗?那么,假设您的“谓词”是工作队列的“状态”,以及一些标志,告诉您停止循环和退出。在接收到“不同”的通知后,您将检查是否应该继续执行循环,并决定是否继续执行,从队列中弹出一些数据。修改队列需要使用互斥锁(记住,它的“状态”是我们谓词的一部分)。一旦我们取出数据,我们就在本地拥有它,并且可以独立于队列状态处理它,所以我们释放互斥锁,做我们的事情,然后要求互斥对象进行下一个操作。有很多方法可以对上述概念进行编码,包括明智地使用pthread_cond_broadcast等,但是基本形式是可以理解的。
This turned out to be considerably longer than I had hoped, but this is a major hurdle for people learning pthread-programming, and I feel it is worth the extra time/effort. I hope you got something out of it.
这比我所希望的要长得多,但这是人们学习pthread-programming的一个主要障碍,我觉得这是值得付出额外的时间/努力的。我希望你能从中得到些什么。
#3
5
yes it unlocks, waits for the condition to be fulfilled and then waits till it can reaquire the passed mutex.
是的,它会解锁,等待条件满足,然后等待,直到它可以重新获得通过的互斥锁。