为什么一个条件全局变量互斥要用互斥全局变量互斥来

博客访问: 848881
博文数量: 158
博客积分: 65
博客等级: 民兵
技术积分: 3334
注册时间:
互联网行业新兵
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: LINUX
互斥锁和条件变量是出自Posix线程标准,用来同步一个进程中各个线程的,同时也可以用来同步几个进程间的,不过这需要此互斥锁和条件变量是存放在多个进程间共享的某个内存区的。
互斥锁上锁与解锁:
1 #include
3 int pthread_mutex_lock(pthread_mutex_t *mutex);
4 int pthread_mutex_trylock(pthread_mutex_t *mutex);
5 int pthread_mutex_unlock(pthread_mutex_t *mutex);
互斥锁初始化的问题:
可以通过两种方式初始化一个互斥锁变量:
1,如果互斥锁变量是静态分配的,那么使用如下形式初始化:
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
2,如果互斥锁是动态分配的,那么我么可以用pthread_mutex_init函数初始化它。
1 int pthread_mutex_init(pthread_mutex_t *restrict mutex,
& & & const pthread_mutexattr_t *restrict attr);
这两者有个很关键的地方,静态分配的话,只能使用默认的属性,而对于动态分配的,我们可以设置属性。
条件变量:等待与信号发送:
互斥锁有个劣势,那就是他仅仅是上锁和解锁,效率低,这时我们可以通过引入条件变量来解决问题,它允许一个线程或进程睡眠到某个事件为止。
1 #include
3 int pthread_cond_timedwait(pthread_cond_t *restrict cond,
& & & pthread_mutex_t *restrict mutex,
& & & const struct timespec *restrict abstime);
6 int pthread_cond_wait(pthread_cond_t *restrict cond,
& & & pthread_mutex_t *restrict mutex);
1 #include
3 int pthread_cond_broadcast(pthread_cond_t *cond);
4 int pthread_cond_signal(pthread_cond_t *cond);
每一个条件变量总是有一个互斥锁与之关联,我们再等待某个条件为真时,还会指定条件变量的地址和所关联的互斥锁的地址,这是什么意思呢?就是说,在使用pthread_cond_wait函数之前,我们要先用一个互斥锁锁住,然后当我们调用pthread_cond_wait函数进入睡眠。注意:该函数原子的执行两个动作:
1,给互斥锁解锁。(这就要求在调用这个函数之前要上锁)
2,把调用线程投入睡眠。
一旦这个函数被唤醒后,那么在此函数返回前重新给互斥锁上锁。这也就决定了在接下来的程序里必须有解锁的步骤。
互斥锁和条件变量的属性:
我们可以通过设置属性来选择是一个进程中多个线程同步还是多个进程间的同步。
1 #include
3 int pthread_mutex_destroy(pthread_mutex_t *mutex);
4 int pthread_mutex_init(pthread_mutex_t *restrict mutex,
& & & const pthread_mutexattr_t *restrict attr);
6 int pthread_cond_destroy(pthread_cond_t *cond);
7 int pthread_cond_init(pthread_cond_t *restrict cond,
& & & const pthread_condattr_t *restrict attr);
互斥锁和条件变量的属性如同互斥锁和条件变量一样,也分为静态和动态分配及其初始化。
1 #include
3 int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
4 int pthread_mutexattr_init(pthread_mutexattr_t *attr);
5 int pthread_condattr_destroy(pthread_condattr_t *attr);
6 int pthread_condattr_init(pthread_condattr_t *attr);
至于前面讲到的更改互斥锁和条件变量的属性来达到切换是线程间同步还是进程间同步的问题是通过如下函数来操作的:
01 #include
03 int pthread_mutexattr_getpshared(const pthread_mutexattr_t *
& & & restrict attr, int *restrict pshared);
05 int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,
& & & int pshared);
07 int pthread_condattr_getpshared(const pthread_condattr_t *restrict attr,
& & & int *restrict pshared);
09 int pthread_condattr_setpshared(pthread_condattr_t *attr,
& & & int pshared);
pshared的值就是用来设置这个属性的值,它可以是PTHREAD_PROCESS_PRIVATE(线程间同步)或PTHREAD_PROCESS_SHARED(进程间同步)。
条件变量定时等待和广播:
用来唤醒阻塞在此条件变量上的所有线程。
1 #include
3 int pthread_cond_broadcast(pthread_cond_t *cond);
4 int pthread_cond_timedwait(pthread_cond_t *restrict cond,
& & & pthread_mutex_t *restrict mutex,
& & & const struct timespec *restrict abstime);
7 int pthread_cond_wait(pthread_cond_t *restrict cond,
& & & pthread_mutex_t *restrict mutex);
这里要说明一点,对于第二个函数所提到的abstime,这是绝对时间,而不是我们一般索说到的相差时间,也就是说这个时间是指自UTC时间以来所流逝的秒数和纳秒数,这样就有个一个好处:如果函数因为有信号到来而过早返回了,那么这个函数可以在无需更改参数的情况下继续再次被调用。
互斥锁用于保护代码临界区,从而保证任何时刻只有一个线程或者进程在临界区执行。有时候一个线程获得某个互斥锁后,发现自己需要等待某个条件变为真,这样线程就可以等待在某个条件上。条件变量总是有一个互斥锁与之关联。
互斥锁和条件变量可以静态分配并静态初始化。它们也可以动态分配并要求动态地初始化它们。动态初始化允许我们指定进程间共享属性,从而允许在不同进程间共享某个互斥锁或条件变量,其前提是该互斥锁或条件变量必须存在在由这些进程共享的内存区。
阅读(5254) | 评论(0) | 转发(2) |
相关热门文章
给主人留下些什么吧!~~
请登录后评论。使用互斥量和条件变量实现线程同步控制 - benxintuzi - 博客园
管程(monitor)说明
在并发编程中,管程(monitor)是一个同步构件,管程实现了同一时间点,最多只有一个线程可以执行管程的某个子程序。与那些通过修改数据结构实现互斥访问的并发程序设计相比,管程的实现很大程度上简化了程序设计。
管程可以确保一次只有一个进程执行管程中的程序,因此程序员不需要显式地编写同步代码,但是如果需要就某些特定条件上的同步,则需要定义一些条件结构(condition variable)来实现,并且对条件变量的操作仅有wait()和signal(),如下:
condition x,
x.signal();
调用x.wait()操作可能会使得一个进程挂起,直到另一个进程调用x.signal()操作。与信号量中的signal()操作相比,管程中如果在没有任何进程挂起的情况下调用signal()没有任何作用,而在信号量中,则必然会改变信号量的状态。
一个管程(mointor)的示意图如下所示:
一个mointor中的程序运行前必须首先获取mutex,直至程序运行完成或者线程等待的某个条件发生时才释放mutex。当一个线程执行mointor中的一个子程序时,称为占用(occupy)该mointor,因此必须等到没有其他线程执行管程程序时方可调用管程程序,这是互斥保证。在管程的简单实现中,编译器为每个管程对象自动加入一把私有的mutex(lock),初始状态为unlock,管程中的每个对象入口处执行lock操作,出口处执行unlock操作。
因此设计monitor时至少必须包含mutex(lock) object(互斥量)和condition variables(条件变量)。一个条件变量可以看作是等待该条件发生的线程集合。
注:monitor也称为&线程安全对象/类/模块&。
为何需要条件变量?
考虑如下一个busy waiting loop:
while not(P)
&&& do skip
如果仅有mutex,则线程必须等待P为真时才能继续执行。如此,将会导致其他线程无法进入临界区使得条件P为真,因此该管程可能发生死锁。
可以用条件变量解决。一个条件变量C可以看作是一个线程队列,其中存放的线程正在等待与之关联的条件变为真。当一个线程等待一个条件变量C时,其将mutex释放,然后其他线程就可以进入该管程中,通过改变C的值可以使得条件C满足,因此对条件变量C可以有如下操作:
(1)wait(c, m):线程调用该操作,等待条件C满足后继续执行,在等待过程中,释放mutex,因此此过程中,该线程不占用管程。
(2)signal(c):线程调用该操作表明此时条件C为真。
一个线程发生signal()后,至少有两个线程想要占用包含条件变量的管程:发出signal()操作的线程P,等待条件变量的线程Q,此时有两种选择:
1.非阻塞式条件变量:Q继续等待直到P完成。
2.阻塞式条件变量:P继续等待直到Q完成。
两种条件变量类型
阻塞式条件变量
也被称为霍尔风格(Hoare-style)管程,如下图所示:
每个管程包含两个线程队列e,s,其中:
e:入口队列
s:发出signal的线程队列
对于每个条件变量C,有一个线程队列,用C.q表示,如上图的a.q、b.q,这些队列很多情况下可以实现为FIFO模式。
阻塞式条件变量实现如下:
非阻塞式条件变量
也称为Mesa风格管程,如下图所示:
该模型中,发出signal()操作的线程不会失去管程的占用权,被notified()的线程将会被移到队列e中,相较于阻塞式条件变量,该模型不需要队列s。例如Pthread中的条件变量就采用这种非阻塞模式,即发出signal()操作的线程优先级高于被notified()的线程,要使用这种条件变量:首先利用pthread_mutex_lock获取互斥锁,然后调用pthread_cond_wait在线程睡眠等待之前先释放互斥锁,在其被唤醒后再重新获取互斥锁。关于pthread条件变量如下会有详细介绍。
非阻塞条件变量实现如下:
POSIX同步之互斥锁和条件变量的使用
如下为经典的有界缓冲区问题,可以用生产者/消费者模型描述,示意图如下:
采用互斥量的生产者/消费者代码如下:
1 [root@bogon unp]# cat producer_consumer_mutex.c
2 #include &unistd.h&
3 #include &sys/types.h&
4 #include &pthread.h&
5 #include &stdlib.h&
6 #include &string.h&
7 #include &errno.h&
8 #include &stdio.h&
10 #define CONSUMER_COUNT 1
/* 1个消费者线程 */
11 #define PRODUCER_COUNT 3
/* 3个生产者线程 */
12 #define BUFFERSIZE 10
14 int g_buffer[BUFFERSIZE];
16 unsigned short in = 0;
17 unsigned short out = 0;
19 pthread_mutex_t g_
21 pthread_t g_thread[CONSUMER_COUNT + PRODUCER_COUNT];
/* 存放生产者和消费者的线程号 */
23 void* consumer(void* arg)
int num = (int)
/* 不断消费 */
pthread_mutex_lock(&g_mutex);
/* 打印仓库当前状态 */
for (i = 0; i & BUFFERSIZE; i++)
if (g_buffer[i] == -1)
printf("g_buffer[%d] = %s\n", i, "null");
printf("g_buffer[%d] = %d\n", i, g_buffer[i]);
if (i == out)
printf("g_buffer[%d]可以消费\n", i);
/* 消费产品 */
printf("thread %d 开始消费产品 %d\n", num, g_buffer[out]);
46 sleep(4);
/* 消费一个产品需要4秒 */
g_buffer[out] = -1;
printf("消费完毕\n");
out = (out + 1) % BUFFERSIZE;
pthread_mutex_unlock(&g_mutex);
return NULL;
57 void* producer(void* arg)
int num = (int)
/* 不断生产 */
pthread_mutex_lock(&g_mutex);
/* 打印仓库当前状态 */
for (i = 0; i & BUFFERSIZE; i++)
if (g_buffer[i] == -1)
printf("g_buffer[%d] = %s\n", i, "null");
printf("g_buffer[%d] = %d\n", i, g_buffer[i]);
if (i == in)
printf("g_buffer[%d]可以生产\n", i);
/* 生产产品 */
g_buffer[in]++;
printf("thread %d 开始生产产品 %d\n", num, g_buffer[in]);
/* 生产一个产品需要2秒 */
printf("生产完毕\n");
in = (in + 1) % BUFFERSIZE;
pthread_mutex_unlock(&g_mutex);
return NULL;
91 int main(void)
/* 初始化仓库 */
for (i = 0; i & BUFFERSIZE; i++)
g_buffer[i] = -1;
/* 创建消费者线程,线程号为:[0, CONSUMER_COUNT) */
for (i = 0; i & CONSUMER_COUNT; i++)
pthread_create(&g_thread[i], NULL, consumer, (void*)i);
/* 创建生产者线程,线程号为:[CONSUMER_COUNT, CONSUMER_COUNT + PRODUCER_COUNT) */
for (i = 0; i & PRODUCER_COUNT; i++)
pthread_create(&g_thread[i + CONSUMER_COUNT], NULL, producer, (void*)(i + CONSUMER_COUNT));
/* 等待创建的所有线程退出 */
for (i = 0; i & CONSUMER_COUNT + PRODUCER_COUNT; i++)
pthread_join(g_thread[i], NULL);
119 // output
121 thread 2 开始生产产品 4
122 生产完毕
123 g_buffer[0] = 4
124 g_buffer[1] = 4
125 g_buffer[2] = 4
126 g_buffer[3] = 2
127 g_buffer[3]可以生产
128 g_buffer[4] = 2
129 g_buffer[5] = 1
130 g_buffer[6] = 1
131 g_buffer[7] = 0
132 g_buffer[8] = 0
133 g_buffer[9] = 4
134 thread 1 开始生产产品 3
135 生产完毕
136 g_buffer[0] = 4
137 g_buffer[1] = 4
138 g_buffer[2] = 4
139 g_buffer[3] = 3
140 g_buffer[4] = 2
141 g_buffer[5] = 1
142 g_buffer[6] = 1
143 g_buffer[7] = 0
144 g_buffer[8] = 0
145 g_buffer[9] = 4
146 g_buffer[9]可以消费
147 thread 0 开始消费产品 4
148 消费完毕
但是上述程序中存在一个问题,就是当生产者线程未准备好产品时,消费者线程却在不断执行循环,这种被称为轮转(spinning)或者轮询(polling)的现象是对CPU资源的一大浪费。如下引入条件变量与互斥锁共同工作,互斥锁用于加锁互斥,而条件变量则专注于等待,每个条件变量总是和一个互斥锁关联。
采用条件变量的生产者/消费者代码如下:
1 [root@bogon unp]# cat producer_consumer_condition.c
2 #include &unistd.h&
3 #include &sys/types.h&
4 #include &pthread.h&
5 #include &stdlib.h&
6 #include &string.h&
7 #include &errno.h&
8 #include &stdio.h&
10 #define CONSUMER_COUNT 1
/* 1个消费者线程 */
11 #define PRODUCER_COUNT 3
/* 3个生产者线程 */
12 #define BUFFERSIZE 10
14 int g_buffer[BUFFERSIZE];
16 unsigned short in = 0;
17 unsigned short out = 0;
19 pthread_mutex_t g_
21 typedef struct
pthread_mutex_
pthread_cond_
27 Condition not_empty = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
28 Condition not_full = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
/* 可以消费的产品数量 */
32 pthread_t g_thread[CONSUMER_COUNT + PRODUCER_COUNT];
/* 存放生产者和消费者的线程号 */
34 void* consumer(void* arg)
int num = (int)
/* 不断消费 */
pthread_mutex_lock(&g_mutex);
/* 打印仓库当前状态,(为了便于比较,这段打印临界区依然只使用互斥锁保护) */
for (i = 0; i & BUFFERSIZE; i++)
if (g_buffer[i] == -1)
printf("g_buffer[%d] = %s\n", i, "null");
printf("g_buffer[%d] = %d\n", i, g_buffer[i]);
if (i == out)
printf("g_buffer[%d]可以消费\n", i);
pthread_mutex_unlock(&g_mutex);
/* 消费产品 */
pthread_mutex_lock(&not_empty.mutex);
while (nready == 0)
pthread_cond_wait(&not_empty.cond, &not_empty.mutex);
printf("thread %d 开始消费产品 %d\n", num, g_buffer[out]);
/* 消费一个产品需要4秒 */
g_buffer[out] = -1;
printf("消费完毕\n");
out = (out + 1) % BUFFERSIZE;
pthread_cond_signal(&not_full.cond);
pthread_mutex_unlock(&not_empty.mutex);
return NULL;
76 void* producer(void* arg)
int num = (int)
/* 不断生产 */
pthread_mutex_lock(&g_mutex);
/* 打印仓库当前状态 */
for (i = 0; i & BUFFERSIZE; i++)
if (g_buffer[i] == -1)
printf("g_buffer[%d] = %s\n", i, "null");
printf("g_buffer[%d] = %d\n", i, g_buffer[i]);
if (i == in)
printf("g_buffer[%d]可以生产\n", i);
pthread_mutex_unlock(&g_mutex);
/* 生产产品 */
pthread_mutex_lock(&not_full.mutex);
while (nready == BUFFERSIZE)
pthread_cond_wait(&not_full.cond, &not_full.mutex);
g_buffer[in]++;
printf("thread %d 开始生产产品 %d\n", num, g_buffer[in]);
/* 生产一个产品需要2秒 */
printf("生产完毕\n");
in = (in + 1) % BUFFERSIZE;
pthread_cond_signal(&not_empty.cond);
pthread_mutex_unlock(&not_full.mutex);
return NULL;
118 int main(void)
/* 初始化仓库 */
for (i = 0; i & BUFFERSIZE; i++)
g_buffer[i] = -1;
/* 创建消费者线程,线程号为:[0, CONSUMER_COUNT) */
for (i = 0; i & CONSUMER_COUNT; i++)
pthread_create(&g_thread[i], NULL, consumer, (void*)i);
/* 创建生产者线程,线程号为:[CONSUMER_COUNT, CONSUMER_COUNT + PRODUCER_COUNT) */
for (i = 0; i & PRODUCER_COUNT; i++)
pthread_create(&g_thread[i + CONSUMER_COUNT], NULL, producer, (void*)(i + CONSUMER_COUNT));
/* 等待创建的所有线程退出 */
for (i = 0; i & CONSUMER_COUNT + PRODUCER_COUNT; i++)
pthread_join(g_thread[i], NULL);
146 // output is the same as above
条件变量使用说明:
一个条件变量的改变是原子性的,因此需要一个互斥锁来保证,因此,条件变量的使用代码可以如下:
1 typedef struct
pthread_mutex_
pthread_cond_
// 与条件变量相关的变量声明
7 Condition cond_a = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, ...};
8 Condition cond_b = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, ...};
1.执行signal操作的线程中流程如下:
pthread_mutex_lock(&cond_a.mutex);
// 设置条件为真
pthread_cond_signal(&cond_a.cond);
pthread_mutex_unlock(&cond_a.mutex);
pthread_cond_signal与pthread_mutex_unlock的顺序:如果先signal后unlock,则可以确定signal操作是由lock住cond_a.mutex的线程调用的;如果先unlock后signal,则任一线程都可调用signal操作。如果需要可预见的调度行为,最好先signal后unlock,就像上面那样。
2.执行wait操作的线程中流程如下:
pthread_mutex_lock(&cond_a.mutex);
while (条件为假)
pthread_cond_wait(&cond_a.cond, &cond_a.mutex);
// 修改条件
pthread_mutex_unlock(&cond_a.mutex);
(1)pthread_cond_wait执行如下3个操作:
解锁cond_a.mutex,使得其他线程可以进入以便改变条件
将调用线程阻塞在条件变量cond_a上(睡眠了),直到某个线程将条件设为真
成功返回后(此时某个线程调用了pthread_cond_signal/broadcast)重新对cond_a.mutex加锁。
(2)是否可以将:
while (条件为假)
pthread_cond_wait(&cond_a.cond, &cond_a.mutex);
if (条件为假)
pthread_cond_wait(&cond_a.cond, &cond_a.mutex);
答案是如果将while替换为if,可以发生虚假(spurious)唤醒:即发出signal的线程并为将条件设为真就调用了pthread_cond_signal,此时pthread_cond_wait却成功返回了,如此将导致后续的代码执行失败。因此必须在pthread_cond_wait返回后再次判断条件是否确实为真,即必须使用循环而非条件判断。有了互斥量,为什么还需要条件变量?
我的图书馆
有了互斥量,为什么还需要条件变量?
一。互斥量和条件变量简介
& & & &互斥量(mutex)从本质上说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁。对互斥量进行加锁以后,任何其他试图再次对互斥锁加锁的线程将会阻塞直到当前线程释放该互斥锁。如果释放互斥锁时有多个线程阻塞,所有在该互斥锁上的阻塞线程都会变成可运行状态,第一个变为运行状态的线程可以对互斥锁加锁,其他线程将会看到互斥锁依然被锁住,只能回去再次等待它重新变为可用。
& & & &条件变量(cond)是在多线程程序中用来实现"等待--》唤醒"逻辑常用的方法。条件变量利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使“条件成立”。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。线程在改变条件状态前必须首先锁住互斥量,函数pthread_cond_wait把自己放到等待条件的线程列表上,然后对互斥锁解锁(这两个操作是原子操作)。在函数返回时,互斥量再次被锁住。
二。为什么存在条件变量
& & & &首先,举个例子:在应用程序中有连个线程thread1,thread2,thread3和thread4,有一个int类型的全局变量iCount。iCount初始化为0,thread1和thread2的功能是对iCount的加1,thread3的功能是对iCount的值减1,而thread4的功能是当iCount的值大于等于100时,打印提示信息并重置iCount=0。
& & & &如果使用互斥量,线程代码大概应是下面的样子:
& & & &thread1/2:
& & & &while (1)
& & & & & & &pthread_mutex_lock(&mutex);
& & & & & & &iCount++;
& & & & & & &pthread_mutex_unlock(&mutex);
& & & &thread4:
& & & &while(1)
& & & & & & &pthead_mutex_lock(&mutex);
& & & & & & &if (100 &= iCount)
& & & & & & &{
& & & & & & & & & &printf("iCount &= 100\r\n");
& & & & & & & & & &iCount = 0;
& & & & & & & & & &pthread_mutex_unlock(&mutex);
& & & & & & &}
& & & & & & &else
& & & & & & &{
& & & & & & & & & &pthread_mutex_unlock(&mutex);
& & & & & & &}
& & & &在上面代码中由于thread4并不知道什么时候iCount会大于等于100,所以就会一直在循环判断,但是每次判断都要加锁、解锁(即使本次并没有修改iCount)。这就带来了问题一,CPU浪费严重。所以在代码中添加了sleep(),这样让每次判断都休眠一定时间。但这由带来的第二个问题,如果sleep()的时间比较长,导致thread4处理不够及时,等iCount到了很大的值时才重置。对于上面的两个问题,可以使用条件变量来解决。
& & & 首先看一下使用条件变量后,线程代码大概的样子:
& & & thread1/2:
& & & &while(1)
& & & & & & & &pthread_mutex_lock(&mutex);
& & & & & & & &iCount++;
& & & & & & & &pthread_mutex_unlock(&mutex);
& & & & & & & &if (iCount &= 100)
& & & & & & & &{
& & & & & & & & & & & pthread_cond_signal(&cond);
& & & & & & & &}
& & & &} & & & &&
& & & &thread4:
& & & &while (1)
& & & & & & & pthread_mutex_lock(&mutex);
& & & & & & & while(iCount & 100)
& & & & & & & {
& & & & & & & & & & &pthread_cond_wait(&cond, &mutex);
& & & & & & & }
& & & & & & & printf("iCount &= 100\r\n");
& & & & & & & iCount = 0;
& & & & & & & pthread_mutex_unlock(&mutex);
& & & &从上面的代码可以看出thread4中,当iCount & 100时,会调用pthread_cond_wait。而pthread_cond_wait在上面应经讲到它会释放mutex,然后等待条件变为真返回。当返回时会再次锁住mutex。因为pthread_cond_wait会等待,从而不用一直的轮询,减少CPU的浪费。在thread1和thread2中的函数pthread_cond_signal会唤醒等待cond的线程(即thread4),这样当iCount一到大于等于100就会去唤醒thread4。从而不致出现iCount很大了,thread4才去处理。
& & & 需要注意的一点是在thread4中使用的while (iCount & 100),而不是if (iCount & 100)。这是因为在pthread_cond_singal()和pthread_cond_wait()返回之间有时间差,假如在时间差内,thread3又将iCount减到了100以下了,那么thread4就需要在等待条件为真了。
TA的最新馆藏
喜欢该文的人也喜欢他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)Linux中 条件变量为什么要用互斥锁来保护?_百度知道
Linux中 条件变量为什么要用互斥锁来保护?
如果pthread_cond_wait只有cond*一个参数,pthread_cond_signal也只有cond*一个参数,一个用来等,一个用来唤醒,工作的也挺好的不是么?
所有书所有资料所有人都说“互斥锁用来保护条件变量”“防止竞争”等等,为什么要保护?防止什么竞争?如果所有使用pth...
互斥锁一个明显的缺点是他只有两种状态:锁定和非锁定。而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,他常和互斥锁一起使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其他的某个线程改变了条件变量,他将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。一般说来,条件变量被用来进行线承间的同步。可以总结为:条件变量用在某个线程需要在某种条件才去保护它将要操作的临界区的情况下,从而避免了线程不断轮询检查该条件是否成立而降低效率的情况,这是实现了效率提高。。。在条件满足时,自动退出阻塞,再加锁进行操作。Linux下C编程的条件变量:  条件变量是线程中的东西,就是等待某一条件的发生和信号一样  以下是说明:  条件变量使我们可以睡眠等待某种条件出现。  条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待&条件变量的条件成立&而挂起;另一个线程使&条件成立&(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。
采纳率:77%
只有你打完电话出来开门;/取钥匙就进行修改;/&#47。门关着其他人就进不去了,证明这一次取钥匙已经发生
/线程可以获取到的。打个比方,你进去了就把门关上。其中门就是条件变量;这个钥匙正在被使用,可能会有多个进程或线程去修改它;/返回真,表示取钥匙成功
else return false,返回假表示去钥匙失败}就像一个公用电话亭,这就相当于规定了一次只允许一个人进门;取钥匙
if(mutex==true)/&#47,mutex是一个布尔型变量,那么就必须为它添加一个锁,这个锁是每次只有一个进程/否则返回假表示不可借 public synchronized boolean getmutex(){/&#47。在Java里边就用关键字synchronized来指定一个代码块一次只有一个线程可以访问。取钥匙这个函数/方法的算法就可以这么理解了:如果这个锁可借,那么返回真,表示可借,反之为假的时候表示已经有线程在使用这个钥匙,表示这个资源变量(锁)的一个钥匙。为真的是时候表示这个钥匙当前是可以借;钥匙空闲可用
mutex=&#47你不管他是条件变量还是其他什么变量。只要理解,其他人才可以进去。通过synchronized关键字将取钥匙跟进门两个动作放在在一起,绑在一块,释放这个锁,因为这个变量/资源是共享的
也就是说 条件变量的作用也是为了处理资源竞争,而不是简单地“满足x==0就继续”么?
也就是说 条件变量的作用也是为了处理资源竞争,而不是简单地“满足x==0就继续”么?
也就是说 条件变量的作用也是为了处理资源竞争,而不是简单地“满足x==0就继续”么?
你不就是要问的为什么要保护这个变量吗?条件变量就是资源啊。起处理资源竞争作用的应该是这个资源的锁。资源本身应该不具有处理资源竞争的作用。我不知道你实际要解决什么问题,因为你没说清楚,但从你所说的x==0,x应该是一个整数吧。你为这个x添加一个锁,那么就只有一个#程可以获取变量x的钥匙,而获取这个变量的钥匙才能查看和修改这个变量的值,直到这个#程释放这个变量的钥匙。而且在这个#程获取这个变量而没有释放的时候,其他#程是不能获取到这个变量的,包括不能查看这个变量的值,更不能修改,只能等待。没有锁的时候,如果A查看到这个条件变量是满足的,可是在A进行下一步动作之前B修改了这个条件,以至于条件不再满足A,这样A进行下一步的话就会出现异常了。添加一个锁,就可以限定有钥匙的才可以查看。拿到钥匙的可以查看修改直到释放这个钥匙。
本回答被提问者采纳
看看哲学家就餐问题之类的....
看了啊 信号量和条件变量有怎样的关系?和我的问题相似但看完了还是不明白 mutex 为什么是必要的?cond本身就是阻塞的,那mutex肯定就不是为了帮cond阻塞而存在的。那是为了什么?
为您推荐:
其他类似问题
linux的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。

我要回帖

更多关于 条件变量与互斥锁 的文章

 

随机推荐