各位前輩, 初學者最近剛接觸多執行緒, 在練習讀寫鎖時遇到一個問題...
10個執行緒, 8個讀執行緒, 2個寫執行緒, 回圈創建
共享某個 counter 值
讀寫執行緒都列印當前的counter, 同時還有tid 和 創建執行緒時for回圈的計數i
輸出結果:

結果中顯示 i 計數的地方全都是8,
>=========== read 8
而非我想象中的write 0~1, 和 read 0~7
請教下諸位, 這是why, 是我代碼哪里出了問題或是沒有考慮到/知識欠缺的地方?
代碼如下
#define ERROR_THREAD_CREATE(flag) std::cout<<"pthread create error ,flag="<<flag<<std::endl; \
return flag
int counter;
pthread_rwlock_t rwlock;
void *th_write(void *arg)
{
int *i = (int *)arg;
while(1)
{
pthread_rwlock_wrlock(&rwlock);
++counter;
std::cout<<">========== write "<< *i <<" thread: "<<pthread_self()\
<<" counter = "<<counter<<std::endl;
// i 是 回圈創建執行緒時的 for回圈計數
pthread_rwlock_unlock(&rwlock);
usleep(1);
}
return 0;
}
void *th_read(void *arg)
{
int *i = (int*)arg;
while(1)
{
pthread_rwlock_rdlock(&rwlock);
std::cout<<">========== read "<<*i<<" thread: "<<pthread_self()<<" counter = "<<counter<<std::endl;
// i 是 回圈創建執行緒時的 for回圈計數
pthread_rwlock_unlock(&rwlock);
usleep(1);
}
return 0;
}
int insTest()
{
int i;
int res;
pthread_t tids[10];
// 防止寫饑餓
pthread_rwlockattr_t attr;
pthread_rwlockattr_init(&attr);
pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
pthread_rwlock_init(&rwlock, &attr);
for (int k = 0; k < 2; k++)
{
res = pthread_create(&tids[k], NULL, th_write, (void *)&k );
if(res)
{
ERROR_THREAD_CREATE(res);
}
}
for (int i = 0; i < 8; i++)
{
res = pthread_create(&tids[i+2], NULL, th_read, (void *)&i);
if(res)
{
ERROR_THREAD_CREATE(res);
}
}
for (int i = 0; i < 10; i++)
{
pthread_join(tids[i], NULL);
}
pthread_rwlock_destroy(&rwlock);
return 0;
}
int main()
{
insTest();
return 0;
}
uj5u.com熱心網友回復:
因為 pthread_create 的最后一個引數你傳遞的是回圈用變數的指標。uj5u.com熱心網友回復:
問題不少,除了LS說的,還有變數作用范圍的問題for (int k = 0; k < 2; k++) //這里的k是區域變數,離開了for回圈,k理論上被堆疊回收,所以底下的(void *)&k離開for后其實所以非法記憶體操作
{
res = pthread_create(&tids[k], NULL, th_write, (void *)&k ); //這里用的是k的地址,所以兩個寫執行緒用到*th_write(void *arg) 的arg相同
if(res)
{
ERROR_THREAD_CREATE(res);
}
}
for (int i = 0; i < 8; i++) //這里的 i 也是區域變數,可能出現的情況是上面的 k 被回收后,i 重新利用了k的記憶體空間(也就是i和k的地址相同),所以最終k和i都是8
{
res = pthread_create(&tids[i+2], NULL, th_read, (void *)&i); //這里和k的問題一樣,用的是I的地址,8個讀執行緒*th_read(void *arg)的arg相同,同時因為i重復利用了k的記憶體,所以兩個寫執行緒的arg也變為了8(這也就是上面為什么說離開for &k屬于非法記憶體操作)
if(res)
{
ERROR_THREAD_CREATE(res);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/223342.html
標籤:新手樂園
上一篇:陣列
下一篇:QT庫鏈接問題求救
