本篇 ShengYu 要介紹 C/C++ Linux/Unix pthread 建立多執行緒用法與範例,
- pthread 建立新 thread 來執行一個函式
- pthread 建立新 thread 來執行一個函式,且帶入參數
- pthread 建立新 thread 來執行一個類別函式
- pthread detach 不等待 thread 執行結束
- pthread 用陣列建立多個 thread
pthread 建立新 thread 來執行一個函式
pthread 要建立新 thread 的話使用的函式為 pthread_create,
第三個參數為執行緒的函式指標,要注意的是 foo 的函式參數與回傳值類型要符合 pthread_create 的規定,
最後需要使用 pthread_join 來等待 t1 執行完成,這表示主執行緒會停在這一行,直到 t1 thread 執行完成才會往下繼續執行,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22// g++ cpp-pthread_create.cpp -o a.out -pthread
using namespace std;
void * foo(void *arg) {
cout << "foo\n";
pthread_exit(NULL);
cout << "foo 2\n";
return NULL;
}
int main() {
pthread_t t1;
if (pthread_create(&t1, NULL, foo, NULL) != 0) {
cerr << "Error: pthread_create\n";
}
pthread_join(t1, NULL);
return 0;
}
輸出結果如下,1
foo
pthread 建立新 thread 來執行一個函式,且帶入參數
這邊示範 pthread 建立新 thread 如何傳遞參數,分別是傳字串跟傳整數,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33// g++ cpp-pthread_create2.cpp -o a.out -pthread
using namespace std;
void * foo(void *arg) {
cout << "foo, " << (char *)arg << "\n";
return NULL;
}
void * bar(void *arg) {
int *n = (int *)arg;
cout << "bar, " << *n << "\n";
return NULL;
}
int main() {
pthread_t t1;
if (pthread_create(&t1, NULL, foo, (void *)"foo thread") != 0) {
cerr << "Error: pthread_create\n";
}
pthread_t t2;
int n = 10;
if (pthread_create(&t2, NULL, bar, &n) != 0) {
cerr << "Error: pthread_create\n";
}
pthread_join(t1, NULL);
pthread_join(t2, NULL);
return 0;
}
輸出結果如下,1
2foo, foo thread
bar, 10
pthread 建立新 thread 來執行一個類別函式
這邊示範 pthread_create()
在 class 裡建立 thread,並指定成員函式為 FOO::run()
,FOO::run()
需要宣告成 static,可參考下面範例的兩種方式寫法,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49// g++ cpp-pthread_create-class.cpp -o a.out -pthread
using namespace std;
class FOO {
public:
FOO(int id) {
this->id = id;
cout << "FOO id = " << id << "\n";
}
void create_thread() {
if (pthread_create(&t1, NULL, run, this) != 0) {
cerr << "Error: pthread_create\n";
}
}
void join_thread() {
pthread_join(t1, NULL);
}
private:
//static void * run(void *arg);
static void * run(void *arg) {
FOO *self = (FOO *)arg;
cout << "run id = " << self->id << "\n";
return NULL;
}
pthread_t t1;
int id;
};
/*void * FOO::run(void *arg) {
FOO *self = (FOO *)arg;
cout << "run id = " << self->id << "\n";
return NULL;
}*/
int main() {
FOO foo(1);
foo.create_thread();
foo.join_thread();
return 0;
}
結果輸出如下,1
2FOO id = 1
run id = 1
跟上例不同,這邊示範 pthread_create()
在 class 外建立 thread,並指定成員函式為 FOO::run()
,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41// g++ cpp-pthread_create-class2.cpp -o a.out -pthread
using namespace std;
class FOO {
public:
FOO(int id) {
this->id = id;
cout << "FOO id = " << id << "\n";
}
//static void * run(void *arg);
static void * run(void *arg) {
FOO *self = (FOO *)arg;
cout << "run id = " << self->id << "\n";
return NULL;
}
private:
int id;
};
/*void * FOO::run(void *arg) {
FOO *self = (FOO *)arg;
cout << "run id = " << self->id << "\n";
return NULL;
}*/
int main() {
FOO foo(1);
pthread_t t1;
if (pthread_create(&t1, NULL, FOO::run, &foo) != 0) {
cerr << "Error: pthread_create\n";
}
pthread_join(t1, NULL);
return 0;
}
結果輸出同上。
pthread detach 不等待 thread 執行結束
如果主執行緒不想等或是可以不用等待 t1 執行緒的話,
就可以使用 pthread_detach()
來讓 t1 執行緒分離,接著主執行緒就可以繼續執行,t1執行緒也在繼續執行,
也可以在 foo 裡使用 pthread_detach()
使用 pthread_self()
傳入自身的 pthread_t 即可,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25// g++ cpp-pthread_create-detach.cpp -o a.out -pthread
using namespace std;
void * foo(void *arg) {
// pthread_detach(pthread_self());
cout << "foo 1\n";
sleep(1);
cout << "foo 2\n";
//pthread_exit(NULL);
return NULL;
}
int main() {
pthread_t t1;
if (pthread_create(&t1, NULL, foo, NULL) != 0) {
cerr << "Error: pthread_create\n";
}
cout << "main 1\n";
pthread_detach(t1);
cout << "main 2\n";
return 0;
}
輸出結果如下,1
2
3main 1
main 2
foo 1
pthread 用陣列建立多個 thread
這邊示範用陣列建立多個 thread,傳入的參數也變成陣列各自獨立,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28// g++ cpp-pthread_create-array.cpp -o a.out -pthread
using namespace std;
void * foo(void *arg) {
int n = *(int *)arg;
//cout << "foo, n=" << n << "\n" << endl;
printf("foo, n=%d\n", n);
return NULL;
}
int main() {
pthread_t threads[3];
int args[3];
for (int i = 0; i < 3; i++) {
args[i] = i;
if (pthread_create(&threads[i], NULL, foo, &args[i]) != 0) {
cerr << "Error: pthread_create\n";
}
}
for (int i = 0; i < 3; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
執行結果如下,1
2
3foo, n=1
foo, n=0
foo, n=2
這邊要注意一點的是,傳遞參數時需要注意變數的生命週期,否則會遇到該 thread 會拿到無效/非預期的參考資料,如下範例,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using namespace std;
typedef struct {
int id;
int data;
} ThreadArgs;
void * foo(void *args) {
ThreadArgs* threadArgs = (ThreadArgs*)args;
printf("id: %d, data: %d\n", threadArgs->id, threadArgs->data);
pthread_exit(NULL);
return NULL;
}
int main() {
pthread_t threads[3];
for (int i = 0; i < 3; i++) {
ThreadArgs args;
args.id = i;
args.data = i * 2;
if (pthread_create(&threads[i], NULL, foo, &args) != 0) {
cerr << "Error: pthread_create\n";
}
}
for (int i = 0; i < 3; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
輸出結果可能如下,1
2
3id: 2, data: 4
id: 2, data: 4
id: 2, data: 4
修正後的作法應該會變成這樣寫,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38// g++ cpp-pthread_create-array2.cpp -o a.out -pthread
using namespace std;
typedef struct {
int id;
int data;
} ThreadArgs;
void * foo(void *args) {
ThreadArgs* threadArgs = (ThreadArgs*)args;
printf("id: %d, data: %d\n", threadArgs->id, threadArgs->data);
pthread_exit(NULL);
return NULL;
}
int main() {
pthread_t threads[3];
ThreadArgs* args[3];
for (int i = 0; i < 3; i++) {
args[i] = (ThreadArgs*)malloc(sizeof(ThreadArgs));
args[i]->id = i;
args[i]->data = i * 2;
if (pthread_create(&threads[i], NULL, foo, args[i]) != 0) {
cerr << "Error: pthread_create\n";
}
}
for (int i = 0; i < 3; i++) {
pthread_join(threads[i], NULL);
free(args[i]);
}
return 0;
}
輸出結果如下,這次結果就符合我們的預期了,1
2
3id: 0, data: 0
id: 1, data: 2
id: 2, data: 4
以上就是 C/C++ Linux/Unix pthread 建立多執行緒用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!
其它相關文章推薦
C/C++ 新手入門教學懶人包
C/C++ Linux pthread_join 用法與範例
C/C++ Linux pthread_exit 用法與範例
C/C++ Linux pthread_attr_setstacksize 設定執行緒堆疊大小用法
C/C++ sleep 用法與範例
C++ std::thread 建立多執行緒用法與範例