我有一個簡單的片段,其中編譯器優化了變數“done”
#include <pthread.h>
#include <stdbool.h>
bool done = false;
void *func(void *args)
{
done = true;
return NULL;
}
main()
{
pthread_t p1;
pthread_create(&p1, NULL, func, NULL);
printf("waiting\n");
while(!done)
{}
printf("moving on...\n");
}
在這里,在沒有 volatile 關鍵字的情況下,變數“done”被優化掉并進入無限回圈。
我正在編譯使用:
gcc -O2 volatile.c -lpthread
但是當我使用簡單的 func() 版本時:
#include <stdbool.h>
bool done = false;
void func()
{
done = true;
}
main()
{
func();
printf("waiting\n");
while(!done)
{}
printf("moving on...\n");
}
但是這里變數“done”沒有優化出來,兩者有什么區別?
編譯器在第二種情況下猜測出“完成”將如何改變一些但在 Pthread 的情況下不會?
我的 GCC 版本是:
gcc --version gcc (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609
uj5u.com熱心網友回復:
done在任何一種情況下,變數都沒有優化。什么是優化掉(在這兩種情況下)是讀的done在while回圈。該讀取被提升出回圈并在回圈之前發生一次;然后回圈運行 0 次或無限運行,具體取決于done回圈前 read的值。它有效地變成
if (!done)
while (true) {}
else
while (false) {}
然后進一步簡化為
if (!done) while (true) {}
uj5u.com熱心網友回復:
以下建議代碼:
- 包括缺少的頭檔案:'printf()' 和 'fprintf()' 的 'stdio.h'
- 正確退出執行緒函式
- 正確地導致“主”執行緒等待子執行緒以避免“燒毀所有可用的 CPU 周期”
- 正確檢查對“pthread_create()”的呼叫狀態——此函式未設定“errno”
- 正確處理“args”引數以避免編譯器警告
- 消除“無用”變數“完成”
- 對“main()”使用有效簽名
- 包含適當的水平間距以提高可讀性
- 消除不需要的頭檔案'stdbool.h'
現在,建議的代碼:
#include <pthread.h>
#include <stdio.h> // printf(), fprintf()
#include <stdlib.h> // exit() and EXIT_FAILURE
//bool done = false;
void *func( void *args )
{
(void)args; // eliminate warning about unused argument
//done = true;
//return NULL;
pthread_exit( NULL );
}
int main( void ) //use valid signature for 'main()'
{
pthread_t p1;
if( pthread_create( &p1, NULL, func, NULL ) != 0 )
{
fprintf( stderr, "call to pthread_create() failed\n" );
exit( EXIT_FAILURE );
}
printf( "waiting\n" );
pthread_join( p1, NULL ); // wait for sub thread to exit
//while(!done)
//{}
printf( "moving on...\n" );
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/321760.html
