QThread庫(kù)是QT中提供的跨平臺(tái)多線程實(shí)現(xiàn)方案,使用時(shí)需要繼承QThread這個(gè)基類,并重寫實(shí)現(xiàn)內(nèi)部的Run方法,由于該庫(kù)是基本庫(kù),默認(rèn)依賴于QtCore.dll
這個(gè)基礎(chǔ)模塊,在使用時(shí)無(wú)需引入其他模塊.
實(shí)現(xiàn)簡(jiǎn)單多線程
QThread庫(kù)提供了跨平臺(tái)的多線程管理方案,通常一個(gè)QThread對(duì)象管理一個(gè)線程,在使用是需要從QThread類繼承并重寫內(nèi)部的Run方法,并在Run方法內(nèi)部實(shí)現(xiàn)多線程代碼.
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
#include <QCoreApplication> #include <iostream> #include <QThread> class MyThread: public QThread { protected : volatile bool m_to_stop; protected : // 線程函數(shù)必須使用Run作為開(kāi)始 void run() { for ( int x=0; !m_to_stop && (x <10); x++) { msleep(1000); std::cout << objectName().toStdString() << std::endl; } } public : MyThread() { m_to_stop = false ; } // 用于設(shè)置結(jié)束符號(hào)為真 void stop() { m_to_stop = true ; } // 輸出線程運(yùn)行狀態(tài) void is_run() { std::cout << "Thread Running = " << isRunning() << std::endl; } // 輸出線程完成狀態(tài)(是否結(jié)束) void is_finish() { std::cout << "Thread Finished = " << isFinished() << std::endl; } }; int main( int argc, char *argv[]) { QCoreApplication a(argc, argv); // 定義線程數(shù)組 MyThread thread [10]; // 設(shè)置線程對(duì)象名字 for ( int x=0;x<10;x++) { thread [x].setObjectName(QString( "thread => %1" ).arg(x)); } // 批量調(diào)用run執(zhí)行 for ( int x=0;x<10;x++) { thread [x].start(); thread [x].is_run(); thread [x].isFinished(); } // 批量調(diào)用stop關(guān)閉 for ( int x=0;x<10;x++) { thread [x].wait(); thread [x].stop(); thread [x].is_run(); thread [x].is_finish(); } return a.exec(); } |
向線程中傳遞參數(shù)
線程在執(zhí)行前可以通過(guò)調(diào)用MyThread中的自定義函數(shù),并在函數(shù)內(nèi)實(shí)現(xiàn)參數(shù)賦值,實(shí)現(xiàn)線程傳參操作.
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
#include <QCoreApplication> #include <iostream> #include <QThread> class MyThread: public QThread { protected : int m_begin; int m_end; int m_result; void run() { m_result = m_begin + m_end; } public : MyThread() { m_begin = 0; m_end = 0; m_result = 0; } // 設(shè)置參數(shù)給當(dāng)前線程 void set_value( int x, int y) { m_begin = x; m_end = y; } // 獲取當(dāng)前線程名 void get_object_name() { std::cout << "this thread name => " << objectName().toStdString() << std::endl; } // 獲取線程返回結(jié)果 int result() { return m_result; } }; int main( int argc, char *argv[]) { QCoreApplication a(argc, argv); MyThread thread [3]; // 分別將不同的參數(shù)傳入到線程函數(shù)內(nèi) for ( int x=0; x<3; x++) { thread [x].set_value(1,2); thread [x].setObjectName(QString( "thread -> %1" ).arg(x)); thread [x].start(); } // 等待所有線程執(zhí)行結(jié)束 for ( int x=0; x<3; x++) { thread [x].get_object_name(); thread [x].wait(); } // 獲取線程返回值并相加 int result = thread [0].result() + thread [1].result() + thread [2].result(); std::cout << "sum => " << result << std::endl; return a.exec(); } |
QMutex 互斥同步線程鎖
QMutex類是基于互斥量的線程同步鎖,該鎖lock()
鎖定與unlock()
解鎖必須配對(duì)使用,線程鎖保證線程間的互斥,利用線程鎖能夠保證臨界資源的安全性.
- 線程鎖解決的問(wèn)題: 多個(gè)線程同時(shí)操作同一個(gè)全局變量,為了防止資源的無(wú)序覆蓋現(xiàn)象,從而需要增加鎖,來(lái)實(shí)現(xiàn)多線程搶占資源時(shí)可以有序執(zhí)行.
- 臨界資源(Critical Resource): 每次只允許一個(gè)線程進(jìn)行訪問(wèn) (讀/寫)的資源.
- 線程間的互斥(競(jìng)爭(zhēng)): 多個(gè)線程在同一時(shí)刻都需要訪問(wèn)臨界資源.
- 一般性原則: 每一個(gè)臨界資源都需要一個(gè)線程鎖進(jìn)行保護(hù).
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
#include <QCoreApplication> #include <iostream> #include <QThread> #include <QMutex> static QMutex g_mutex; // 線程鎖 static QString g_store; // 定義全局變量 class Producer : public QThread { protected : void run() { int count = 0; while ( true ) { // 加鎖 g_mutex.lock(); g_store.append(QString::number((count++) % 10)); std::cout << "Producer -> " << g_store.toStdString() << std::endl; // 釋放鎖 g_mutex.unlock(); msleep(900); } } }; class Customer : public QThread { protected : void run() { while ( true ) { g_mutex.lock(); if ( g_store != "" ) { g_store. remove (0, 1); std::cout << "Curstomer -> " << g_store.toStdString() << std::endl; } g_mutex.unlock(); msleep(1000); } } }; int main( int argc, char *argv[]) { QCoreApplication a(argc, argv); Producer p; Customer c; p.setObjectName( "producer" ); c.setObjectName( "curstomer" ); p.start(); c.start(); return a.exec(); } |
QMutexLocker是在QMutex基礎(chǔ)上簡(jiǎn)化版的線程鎖,QMutexLocker會(huì)保護(hù)加鎖區(qū)域,并自動(dòng)實(shí)現(xiàn)互斥量的鎖定和解鎖操作,可以將其理解為是智能版的QMutex鎖,該鎖只需要在上方代碼中稍加修改即可.
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
|
#include <QMutex> #include <QMutexLocker> static QMutex g_mutex; // 線程鎖 static QString g_store; // 定義全局變量 class Producer : public QThread { protected : void run() { int count = 0; while ( true ) { // 增加智能線程鎖 QMutexLocker Locker(&g_mutex); g_store.append(QString::number((count++) % 10)); std::cout << "Producer -> " << g_store.toStdString() << std::endl; msleep(900); } } }; |
互斥鎖存在一個(gè)問(wèn)題,每次只能有一個(gè)線程獲得互斥量的權(quán)限,如果在程序中有多個(gè)線程來(lái)同時(shí)讀取某個(gè)變量,那么使用互斥量必須排隊(duì),效率上會(huì)大打折扣,基于QReadWriteLock
讀寫模式進(jìn)行代碼段鎖定,即可解決互斥鎖存在的問(wèn)題.
QReadWriteLock 讀寫同步線程鎖
該鎖允許用戶以同步讀lockForRead()
或同步寫lockForWrite()
兩種方式實(shí)現(xiàn)保護(hù)資源,但只要有一個(gè)線程在以寫的方式操作資源,其他線程也會(huì)等待寫入操作結(jié)束后才可繼續(xù)讀資源.
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
#include <QCoreApplication> #include <iostream> #include <QThread> #include <QMutex> #include <QReadWriteLock> static QReadWriteLock g_mutex; // 線程鎖 static QString g_store; // 定義全局變量 class Producer : public QThread { protected : void run() { int count = 0; while ( true ) { // 以寫入方式鎖定資源 g_mutex.lockForWrite(); g_store.append(QString::number((count++) % 10)); // 寫入后解鎖資源 g_mutex.unlock(); msleep(900); } } }; class Customer : public QThread { protected : void run() { while ( true ) { // 以讀取方式寫入資源 g_mutex.lockForRead(); if ( g_store != "" ) { std::cout << "Curstomer -> " << g_store.toStdString() << std::endl; } // 讀取到后解鎖資源 g_mutex.unlock(); msleep(1000); } } }; int main( int argc, char *argv[]) { QCoreApplication a(argc, argv); Producer p1,p2; Customer c1,c2; p1.setObjectName( "producer 1" ); p2.setObjectName( "producer 2" ); c1.setObjectName( "curstomer 1" ); c2.setObjectName( "curstomer 2" ); p1.start(); p2.start(); c1.start(); c2.start(); return a.exec(); } |
QSemaphore 基于信號(hào)線程鎖
信號(hào)量是特殊的線程鎖,信號(hào)量允許N個(gè)線程同時(shí)訪問(wèn)臨界資源,通過(guò)acquire()
獲取到指定資源,release()
釋放指定資源.
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
#include <QCoreApplication> #include <iostream> #include <QThread> #include <QSemaphore> const int SIZE = 5; unsigned char g_buff[SIZE] = {0}; QSemaphore g_sem_free(SIZE); // 5個(gè)可生產(chǎn)資源 QSemaphore g_sem_used(0); // 0個(gè)可消費(fèi)資源 // 生產(chǎn)者生產(chǎn)產(chǎn)品 class Producer : public QThread { protected : void run() { while ( true ) { int value = qrand() % 256; // 若無(wú)法獲得可生產(chǎn)資源,阻塞在這里 g_sem_free.acquire(); for ( int i=0; i<SIZE; i++) { if ( !g_buff[i] ) { g_buff[i] = value; std::cout << objectName().toStdString() << " --> " << value << std::endl; break ; } } // 可消費(fèi)資源數(shù)+1 g_sem_used.release(); sleep(2); } } }; // 消費(fèi)者消費(fèi)產(chǎn)品 class Customer : public QThread { protected : void run() { while ( true ) { // 若無(wú)法獲得可消費(fèi)資源,阻塞在這里 g_sem_used.acquire(); for ( int i=0; i<SIZE; i++) { if ( g_buff[i] ) { int value = g_buff[i]; g_buff[i] = 0; std::cout << objectName().toStdString() << " --> " << value << std::endl; break ; } } // 可生產(chǎn)資源數(shù)+1 g_sem_free.release(); sleep(1); } } }; int main( int argc, char *argv[]) { QCoreApplication a(argc, argv); Producer p1; Customer c1; p1.setObjectName( "producer" ); c1.setObjectName( "curstomer" ); p1.start(); c1.start(); return a.exec(); } |
到此這篇關(guān)于C/C++ Qt QThread線程組件的具體使用的文章就介紹到這了,更多相關(guān)Qt QThread線程使用內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
原文鏈接:https://www.cnblogs.com/LyShark/p/15555343.html