linux 线程在未同步的情况下,输出着实没看懂!
/*使用原子锁实现线程同步*/#include <alsa/iatomic.h>
#include <pthread.h>
#include <stdio.h>
// 定义一个原子变量
static atomic_t g_atomic;
// 定义共享资源
static volatile int g_i = 0;
/* 定义线程处理函数 */
#define atomic_dec_and_test(g_atomic) 1
void *thr1_handle(void *arg)
{
while (1) {
if (atomic_dec_and_test(&g_atomic)) {
printf("in thread %lu g_i = %d\n", pthread_self(), ++g_i);
}
atomic_inc(&g_atomic);
sleep(1);
}
return NULL;
}
void *thr2_handle(void *arg)
{
while (1) {
if (atomic_dec_and_test(&g_atomic)) {
printf("in thread %lu g_i = %d\n", pthread_self(), --g_i);
}
atomic_inc(&g_atomic);
sleep(1);
}
return NULL;
}
/* 主函数 */
int main()
{
// 主线程初始化原子变量
//g_atomic = ATOMIC_INIT(0);
g_atomic.counter = 1;
pthread_t tid1, tid2;
if (pthread_create(&tid1, NULL, thr1_handle, NULL) != 0) {
fprintf(stderr, "create thread1 failed!\n");
return 1;
}
if (pthread_create(&tid2, NULL, thr2_handle, NULL) != 0) {
fprintf(stderr, "create thread2 failed!\n");
return 2;
}
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}在不使用原子操作来做同步的情况下,程序输出如下:
in thread 3075713856 g_i = 1
in thread 3067321152 g_i = 0
in thread 3067321152 g_i = -1
in thread 3075713856 g_i = 1
in thread 3067321152 g_i = 0
in thread 3075713856 g_i = 1
in thread 3075713856 g_i = 2
in thread 3067321152 g_i = 0
in thread 3075713856 g_i = 3
in thread 3067321152 g_i = 1
in thread 3075713856 g_i = 4
in thread 3067321152 g_i = 2
in thread 3075713856 g_i = 5
in thread 3067321152 g_i = 3
in thread 3075713856 g_i = 6
in thread 3067321152 g_i = 5
in thread 3067321152 g_i = 4
in thread 3075713856 g_i = 6
in thread 3075713856 g_i = 5
in thread 3067321152 g_i = 3
in thread 3075713856 g_i = 6
in thread 3067321152 g_i = 4
in thread 3067321152 g_i = 3
in thread 3075713856 g_i = 5
in thread 3075713856 g_i = 6
in thread 3067321152 g_i = 4
in thread 3067321152 g_i = 5
in thread 3075713856 g_i = 6
in thread 3075713856 g_i = 7
in thread 3067321152 g_i = 5
在输出标红的部分,线程切换时为什么值会出现跳跃增加或减少呢?
按照程序逻辑,在没进入线程一次,只做一次值的加或减呀,怎是怎么个情况? 期待大V指点下 将++g_i(或--g_i)理解为一下三句,就能解释这样的输出产生的原因:
register = memory(g_i);
register = register + 1(或register = register - 1);
memory(g_i) = register;
井蛙夏虫 发表于 2014-04-06 00:23 static/image/common/back.gif
将++g_i(或--g_i)理解为一下三句,就能解释这样的输出产生的原因:
register = memory(g_i);
register = r ...
谢谢你,井蛙夏虫!
你的意思是说 前++/--这种操作被打断导致上面的情况。可是我不是太明白,请原谅我的愚昧
printf ++g_i 的时候,打印的就是 g_i 所在内存的值,即:
in thread 3075713856 g_i = 1 此时 g_i 内存单元的值为 1
in thread 3075713856 g_i = 2 此时 g_i 内存单元的值为 2
in thread 3067321152 g_i = 0 此时线程切换,--g_i 是取g_i内存的值然后减1,然后将值压入printf的函数栈,怎么就变成0了呢?
in thread 3075713856 g_i = 3
in thread 3067321152 g_i = 1
in thread 3075713856 g_i = 4
期待你的更详细的讲解。 2楼都写明白了吧,++和--都不是atomic操作,为什么还是将--g_i理解为一次执行完毕呢?请至少分为三个独立指令,而且执行每个指令后,都可能切换到另外一个线程。
BTW:这算典型的undefined行为,知道不可取就可以了,还深究什么?就好比“malloc一次,free两次,为什么有时候core,有时不core?”,点到即止。 timespace 发表于 2014-04-06 18:44 static/image/common/back.gif
2楼都写明白了吧,++和--都不是atomic操作,为什么还是将--g_i理解为一次执行完毕呢?请至少分为三个独立指 ...
谢谢指点。
我已知道 ++/-- 不是原子操作,可是我还是不是很明白,能给我做一个深度剖析吗?
in thread 3075713856 g_i = 1 正常
in thread 3067321152 g_i = 0 正常
in thread 3067321152 g_i = -1 正常
in thread 3075713856 g_i = 1 不正常
in thread 3067321152 g_i = 0 正常
in thread 3075713856 g_i = 1 正常
in thread 3075713856 g_i = 2 正常
in thread 3067321152 g_i = 0 不正常
in thread 3075713856 g_i = 3 不正常
in thread 3067321152 g_i = 1 不正常
in thread 3075713856 g_i = 4 不正常
in thread 3067321152 g_i = 2 不正常
in thread 3075713856 g_i = 5 不正常
in thread 3067321152 g_i = 3 不正常
in thread 3075713856 g_i = 6 不正常
从地一个不正常分析。
在本次打印之前,线程3067321152已将g_i的值修改为-1,然后在本次打印的结果却是 1 ,说明本次取到的 g_i 的值为0. 从上面的线程执行情况看,只有在第二行的时候值为0,即在线程 3067321152 中。 难道是in thread 3067321152 g_i = -1还没有及时写入内存,此时发生线程切换,切换到 in thread 3075713856 g_i = 1,这个时候取到的就是 0
不知道这样理解对不对。 线程栈相互独立,有各自的寄存器。
/* 从输出1~4行推断,第3行输出之前g_i = 0 ,下面分解第3行和第4行可能执行顺序 */
t1(++) r1 = g_i /* r1是t1的寄存器, g_i = 0那么 r1= 0 */
t2(--) r2 = g_i /* r2 = 0 */
t1(++) r1 += 1 /* r1 = 1 */
t2(--) r2 -= 1 /* r2 = -1 */
t2(--) g_i = r2 /* g_i = -1 */
t1(++) g_i = r1 /* g_i = 1 */
/* 不同步,执行是随机的,出现其它结果也不奇怪 */ timespace 发表于 2014-04-06 22:15 static/image/common/back.gif
线程栈相互独立,有各自的寄存器。
/* 从输出1~4行推断,第3行输出之前g_i = 0 ,下面分解第3行和第4行可 ...
恩,看来我在上一楼的理解是对的。
谢谢你这直观的分析!
页:
[1]