linux多进程条件变量,Linux多线程4-3_条件变量

//包含头文件

int pthread_cond_timedwait(pthread_cond_t *restrict cond,  pthread_mutex_t *restrict mutex,  const struct timespec *restrict abstime);

int pthread_cond_wait(pthread_cond_t *restrict cond,  pthread_mutex_t *restrict mutex);

DESCRIPTION

The pthread_cond_timedwait() and pthread_cond_wait() functions shall block on a condition variable. They shall be called

with mutex locked by the calling thread or undefined behavior results.

//pthread_cond_timedwait() and pthread_cond_wait()会阻塞一个条件变量,他们应该配合互斥量使用,否则结果是未知的

These functions atomically release mutex and cause the calling thread to block on the condition  variable  cond;  atomi-

cally  here  means  "atomically  with respect to access by another thread to the mutex and then the condition variable".

That is, if another thread is able to acquire the mutex after the about-to-block thread has released it, then  a  subse-

quent  call  to pthread_cond_broadcast() or pthread_cond_signal() in that thread shall behave as if it were issued after

the about-to-block thread has blocked.

//这个函数会将mutex释放,同时将线程阻塞,这是一个原子操作。其他的线程就可以去拥有互斥量了,然后释放一个信号

//通知其他阻塞的线程,条件已经被满足了

Upon successful return, the mutex shall have been locked and shall be owned by the calling thread.

//成功的返回之后,互斥量被加锁,被当前线程拥有

When using condition variables there is always a Boolean predicate involving shared variables associated with each  con-

dition  wait  that  is  true  if  the  thread  should  proceed.  Spurious  wakeups  from the pthread_cond_timedwait() or

pthread_cond_wait() functions may occur. Since the return from pthread_cond_timedwait() or pthread_cond_wait() does  not

imply anything about the value of this predicate, the predicate should be re-evaluated upon such return.

//使用条件变量的时候通常配有一个布尔类型的变量,如果这个变量是真,那么线程就应该向前执行。pthread_cond_timedwait()

//or pthread_cond_wait()并不知道这个变量的值,因此当他们返回之后,这个变量要重新被赋值

The effect of using more than one mutex for concurrent pthread_cond_timedwait() or pthread_cond_wait() operations on the

same condition variable is undefined; that is, a condition variable becomes bound to a unique mutex when a thread  waits

on the condition variable, and this (dynamic) binding shall end when the wait returns.

//一个条件变量只绑定一个互斥量使用,如果有多个互斥量绑定了同一个条件变量,那么结果是未知的

A  condition wait (whether timed or not) is a cancellation point. When the cancelability enable state of a thread is set

to PTHREAD_CANCEL_DEFERRED, a side effect of acting upon a cancellation request while in a condition wait  is  that  the

mutex  is  (in effect) re-acquired before calling the first cancellation cleanup handler. The effect is as if the thread

were unblocked, allowed to execute  up  to  the  point  of  returning  from  the  call  to  pthread_cond_timedwait()  or

pthread_cond_wait(),  but  at  that  point  notices  the  cancellation request and instead of returning to the caller of

pthread_cond_timedwait() or pthread_cond_wait(), starts the thread cancellation activities, which includes calling  can-

cellation cleanup handlers.

//条件等待是一个取消点。当线程的取消状态是延迟的,那么在条件等待的时候取消一个线程会导致互斥量被重新获取。

A  thread  that  has  been unblocked because it has been canceled while blocked in a call to pthread_cond_timedwait() or

pthread_cond_wait() shall not consume any condition signal that may be directed concurrently at the  condition  variable

if there are other threads blocked on the condition variable.

//如果一个线程阻塞在pthread_cond_timedwait() 或pthread_cond_wait(),取消它将导致它变的不阻塞,也不回发生任何信号

The  pthread_cond_timedwait()  function  shall be equivalent to pthread_cond_wait(), except that an error is returned if

the absolute time specified by abstime passes (that is, system time equals or exceeds abstime) before the condition cond

is  signaled  or  broadcasted,  or  if the absolute time specified by abstime has already been passed at the time of the

call.

//pthread_cond_timedwait() 和pthread_cond_wait()几乎是等价的,除了pthread_cond_timedwait() 会产生一个超时信号

If the Clock Selection option is supported, the condition variable shall have a  clock  attribute  which  specifies  the

clock  that  shall  be  used  to  measure  the  time  specified  by  the  abstime  argument.   When such timeouts occur,

pthread_cond_timedwait() shall nonetheless release and re-acquire the mutex referenced by mutex. The pthread_cond_timed-

wait() function is also a cancellation point.

//如果时钟选项被支持,那么条件变量会有一个时钟的属性去测量时间。如果时间到了,那么pthread_cond_timedwait()会返回

//而且重新去获取互斥量。pthread_cond_timedwait()也是一个取消点

If  a  signal  is delivered to a thread waiting for a condition variable, upon return from the signal handler the thread

resumes waiting for the condition variable as if it was not interrupted, or it shall return zero due to spurious wakeup.

//如果有信号发送给等待条件的线程,那么当信号处理函数返回之后,线程继续等待条件变量,好像它从未被打断

RETURN VALUE

Except  in the case of [ETIMEDOUT], all these error checks shall act as if they were performed immediately at the begin-

ning of processing for the function and shall cause an error return, in effect, prior to  modifying  the  state  of  the

mutex specified by mutex or the condition variable specified by cond.

//除了ETIMEDOUT,其他所有的错误检测就好像在线程的一开始就已经工作了

Upon  successful completion, a value of zero shall be returned; otherwise, an error number shall be returned to indicate

the error.

//成功的返回0,失败返回错误码

ERRORS

The pthread_cond_timedwait() function shall fail if:

//pthread_cond_timedwait()会在一下情况失败

ETIMEDOUT

The time specified by abstime to pthread_cond_timedwait() has passed.

//设定的超时时间已经过了

The pthread_cond_timedwait() and pthread_cond_wait() functions may fail if:

//pthread_cond_timedwait() 和pthread_cond_wait()会在以下情况失败

EINVAL The value specified by cond, mutex, or abstime is invalid.

//指定的条件变量、互斥量、时间无效

EINVAL Different mutexes were supplied for concurrent pthread_cond_timedwait() or pthread_cond_wait() operations on  the

same condition variable.

//对一个条件变量绑定了不同的互斥量

EPERM  The mutex was not owned by the current thread at the time of the call.

//互斥量不被当前线程拥有

These functions shall not return an error code of [EINTR].

//不会返回EINTR

PTHREAD_COND_BROADCAST(3P) POSIX Programmer’s ManualPTHREAD_COND_BROADCAST(3P)

PROLOG

This  manual page is part of the POSIX Programmer’s Manual.  The Linux implementation of this interface may differ (con-

sult the corresponding Linux manual page for details of Linux behavior), or the interface  may  not  be  implemented  on

Linux.

//这只是POSIX的手册,Linux对这个接口的实现可能不一样,或者有的根本没有实现这个接口

NAME

pthread_cond_broadcast, pthread_cond_signal - broadcast or signal a condition

//广播或者发送一个条件

SYNOPSIS

#include //包含头文件

int pthread_cond_broadcast(pthread_cond_t *cond);

int pthread_cond_signal(pthread_cond_t *cond);

DESCRIPTION

These functions shall unblock threads blocked on a condition variable.

//在条件满足的情况下解锁一个阻塞的线程

The  pthread_cond_broadcast()  function  shall unblock all threads currently blocked on the specified condition variable

cond.

//pthread_cond_broadcast()将当前所有因为这个条件阻塞的线程解锁

The pthread_cond_signal() function shall unblock at least one of the threads that are blocked on the specified condition

variable cond (if any threads are blocked on cond).

//解锁至少一个因为这个条件阻塞的线程

If  more  than  one  thread is blocked on a condition variable, the scheduling policy shall determine the order in which

threads are unblocked. When each thread unblocked as a result of  a  pthread_cond_broadcast()  or  pthread_cond_signal()

returns  from  its call to pthread_cond_wait() or pthread_cond_timedwait(), the thread shall own the mutex with which it

called pthread_cond_wait() or pthread_cond_timedwait(). The thread(s) that are unblocked shall  contend  for  the  mutex

according to the scheduling policy (if applicable), and as if each had called pthread_mutex_lock().

//如果有多个线程因为条件阻塞,那么系统调度会决定让哪一个线程解锁。解锁的那个线程会拥有互斥量

The  pthread_cond_broadcast()  or  pthread_cond_signal() functions may be called by a thread whether or not it currently

owns the mutex that threads calling pthread_cond_wait() or pthread_cond_timedwait() have associated with  the  condition

variable during their waits; however, if predictable scheduling behavior is required, then that mutex shall be locked by

the thread calling pthread_cond_broadcast() or pthread_cond_signal().

The pthread_cond_broadcast() and pthread_cond_signal() functions shall have no effect if there are no threads  currently

blocked on cond.

//如果当前没有线程阻塞,那么这两个函数就没有任何效果

RETURN VALUE

If  successful,  the pthread_cond_broadcast() and pthread_cond_signal() functions shall return zero; otherwise, an error

number shall be returned to indicate the error.

//成功返回0,失败返回错误码

ERRORS

The pthread_cond_broadcast() and pthread_cond_signal() function may fail if:

//以下情况会导致失败

EINVAL The value cond does not refer to an initialized condition variable.

//条件变量没有初始化

These functions shall not return an error code of [EINTR].

//不会返回EINTR

EXAMPLES

None.

五、实例,生产者与消费者问题

1、程序框架

c6b6ac81eb37b9984ae24c181f454f59.png

2、源代码

点击(此处)折叠或打开

/*DATE:    2015-4-6

*AUTHOR:DDDDD

*DESCRIPTION: 生产者与消费者问题

*/

#include "apue.h"

#define BUFFER_SIZE 5 //产品库存大小

#define PRODUCT_CNT 30 //产品生产总数

struct product_cons

{

int buffer[BUFFER_SIZE]; //生产产品值

pthread_mutex_t lock; //互斥锁 volatile int

int readpos, writepos; //读写位置

pthread_cond_t notempty; //条件变量,非空

pthread_cond_t notfull; //非满

}buffer;

void init(struct product_cons *p)

{

pthread_mutex_init(&p->lock, NULL); //互斥锁

pthread_cond_init(&p->notempty, NULL); //条件变量

pthread_cond_init(&p->notfull, NULL); //条件变量

p->readpos = 0; //读写位置

p->writepos = 0;

}

void finish(struct product_cons *p)

{

pthread_mutex_destroy(&p->lock); //互斥锁

pthread_cond_destroy(&p->notempty); //条件变量

pthread_cond_destroy(&p->notfull); //条件变量

p->readpos = 0; //读写位置

p->writepos = 0;

}

//存储 一个数据 到 bufferr

void put(struct product_cons *p, int data) //输入产品子函数

{

pthread_mutex_lock(&p->lock);

if((p->writepos+1)%BUFFER_SIZE == p->readpos)

{

printf("producer wait for not full\n");

pthread_cond_wait(&p->notfull, &p->lock);

}

p->buffer[p->writepos] = data;

p->writepos ++;

if(p->writepos >= BUFFER_SIZE)

p->writepos = 0;

pthread_cond_signal(&p->notempty);

pthread_mutex_unlock(&p->lock);

}

//读,移除 一个数据 从 buffer

int get(struct product_cons *p)

{

int data;

pthread_mutex_lock(&p->lock);

if(p->readpos == p->writepos)

{

printf("consumer wait for not empty\n");

pthread_cond_wait(&p->notempty, &p->lock);

}

data = p->buffer[p->readpos];

p->readpos++;

if(p->readpos >= BUFFER_SIZE)

p->readpos = 0;

pthread_cond_signal(&p->notfull);

pthread_mutex_unlock(&p->lock);

return data;

}

void *producer(void *data) //子线程 ,生产

{

int n;

for(n = 1; n <= 50; ++n) //生产 50 个产品

{

sleep(1);

printf("put the %d product ...\n", n);

put(&buffer,n);

printf("put the %d product success\n", n);

}

printf("producer stopped\n");

return NULL;

}

void *consumer(void *data)

{

static int cnt = 0;

int num;

while(1)

{

sleep(2);

printf("get product ...\n");

num = get(&buffer);

printf("get the %d product success\n", num);

if(++cnt == PRODUCT_CNT)

break;

}

printf("consumer stopped\n");

return NULL;

}

int main(int argc, char *argv[])

{

pthread_t th_a,th_b;

void *retval;

init(&buffer);

pthread_create(&th_a, NULL, producer, 0);

pthread_create(&th_b, NULL, consumer, 0);

pthread_join(th_a, &retval);

pthread_join(th_b, &retval);

finish(&buffer);

return 0;

}

3、作业:多个生产者与多个消费者

点击(此处)折叠或打开

/*多个生产者和多个消费者*/

#include "apue.h"

#define BUFFER_SIZE 5 //产品库存大小

#define PRODUCT_CNT 50 //产品生产总数

struct product_cons

{

int buffer[BUFFER_SIZE]; //生产产品值

pthread_mutex_t lock; //互斥锁 volatile int

int readpos, writepos; //读写位置

pthread_cond_t notempty; //条件变量,非空

pthread_cond_t notfull; //非满

pthread_mutex_t lock2; //互斥锁,控制cnt_p

int cnt_p; //完成生产产品数量

pthread_mutex_t lock3; //互斥锁,控制cnt_c

int cnt_c; //获得生产产品数量

}buffer;

void init(struct product_cons *p)

{

pthread_mutex_init(&p->lock, NULL); //互斥锁

pthread_cond_init(&p->notempty, NULL); //条件变量

pthread_cond_init(&p->notfull, NULL); //条件变量

p->readpos = 0; //读写位置

p->writepos = 0;

pthread_mutex_init(&p->lock2, NULL);

p->cnt_p = 0;

pthread_mutex_init(&p->lock3, NULL);

p->cnt_c = 0;

}

void fini(struct product_cons *p)

{

pthread_mutex_destroy(&p->lock); //互斥锁

pthread_cond_destroy(&p->notempty); //条件变量

pthread_cond_destroy(&p->notfull); //条件变量

p->readpos = 0; //读写位置

p->writepos = 0;

pthread_mutex_destroy(&p->lock2);

p->cnt_p = 0;

pthread_mutex_destroy(&p->lock3);

p->cnt_c = 0;

}

//存储 一个数据 到 bufferr

void put(struct product_cons *p, int data) //输入产品子函数

{

pthread_mutex_lock(&p->lock); //上锁

/*等待,直到 buffer 不为 满*/

while((p->writepos + 1) % BUFFER_SIZE == p->readpos) //测试空间是否已满

{

printf("producer wait for not full\n");

pthread_cond_wait(&p->notfull, &p->lock); //阻塞等待

//这里,生产者 notfull 等待消费者 pthread_cond_signal(&p->notfull);信号

//如果,消费者发送了 signal 信号,表示有了 空闲

}

p->buffer[p->writepos] = data; //写数据

p->writepos++;

if(p->writepos >= BUFFER_SIZE) //如果写到 尾部,返回

p->writepos = 0;

pthread_cond_signal(&p->notempty); //发送有数据信号

pthread_mutex_unlock(&p->lock); //解锁

}

//读,移除 一个数据 从 buffer

int get(struct product_cons *p)

{

int data = 0;

pthread_mutex_lock(&p->lock);

/*等待,直到不为空*/

while(p->writepos == p->readpos)

{

printf("consumer wait for not empty\n");

pthread_cond_wait(&p->notempty,&p->lock);

}

/*读 一个 数据*/

data = p->buffer[p->readpos];

p->readpos++;

if(p->readpos >= BUFFER_SIZE) //如果读到 尾

p->readpos = 0;

pthread_cond_signal(&p->notfull);

pthread_mutex_unlock(&p->lock);

return data;

}

void *producer(void *data) //子线程 ,生产

{

int flag = -1;

while(1)

{

pthread_mutex_lock(&buffer.lock2);

if(buffer.cnt_p < PRODUCT_CNT)

{

++buffer.cnt_p;

printf("%s put the %d product\n", (char*)data, buffer.cnt_p);

put(&buffer, buffer.cnt_p);

}

else

flag = 0;

pthread_mutex_unlock(&buffer.lock2);

if(!flag)

break;

sleep(2);

}

printf("%s producer stopped\n", (char*)data);

return NULL;

}

void *consumer(void *data)

{

int flag = -1;

while(1)

{

pthread_mutex_lock(&buffer.lock3);

if(buffer.cnt_c < PRODUCT_CNT)

{

printf("%s get the %d product\n", (char*)data, get(&buffer));

++buffer.cnt_c;

}

else

flag = 0;

pthread_mutex_unlock(&buffer.lock3);

if(!flag)

break;

sleep(2);

}

printf("%s consumer stopped\n", (char*)data);

return NULL;

}

int main(int argc, char *argv[])

{

pthread_t th_a[3],th_b[3];

void *retval;

init(&buffer);

pthread_create(&th_a[0], NULL, producer, (void*)"th_a[0]");

pthread_create(&th_a[1], NULL, producer, (void*)"th_a[1]");

pthread_create(&th_a[2], NULL, producer, (void*)"th_a[2]");

pthread_create(&th_b[0], NULL, consumer, (void*)"th_b[0]");

pthread_create(&th_b[1], NULL, consumer, (void*)"th_b[1]");

pthread_create(&th_b[2], NULL, consumer, (void*)"th_b[2]");

pthread_join(th_a[0], &retval);

pthread_join(th_a[1], &retval);

pthread_join(th_a[2], &retval);

pthread_join(th_b[0], &retval);

pthread_join(th_b[1], &retval);

pthread_join(th_b[2], &retval);

fini(&buffer);

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值