1.什么是类的线程安全(或线程安全的类)?
了解多线程的人太概都知道,类地线是玄全比可重入更加严格、它要求在不回线程同过调用类回一实侧的成局画数、而不会发程序的递溃。
2.哪些情况下不用考虑线程安全问题?
2.1在多线程中对bool,int,float,QString等类型的操作,你不用考虑任何安全性问题。
因为你无论以什么方式在不同线程中对这些类型进行操作,都像真正的原子性操作一样(其实不是严格的原子性操作),完全不会引起程序崩溃。我想这可能是QT已经对这些类型进行了线程安全保障。
比如,我下面的这个类本身就是线程安全的:
1 class Counter:public QObject
2 {
3 Q_OBJECT
4 public:
5 Counter(){n=0;}
6 void O1(){++n:}
7 void O2(){-n;}
8 int get()const{return n:}
9 private:
10 int n;
11 };
2.2在多线程中使用信号槽机制进行资源共享时,不用考虑线程安全问题。
例如在两个不同的子线程中通过信号槽将字符串信息传递到Ul线程,用于更新界面的显示,这个操作是线程安全的,因为信号槽作为QT独创的通信机制,是线程安全的。
3.设计一个线程安全的类
3.1先展示一个未进行线程安全保障的类是如何引发崩溃的
定义一个非线程安全的类:
1 class Thread1: public QThread
2 {
3 public:
4 Thread1();
5 virtual void run() override;
6 }
7 class Thread2: public QThread
8 {
9 public:
10 Thread2();
11 virtual void run() override;
12 }
在两个子线程中对这个类的同一实例进行访问:
不出意外,程序运行一分钟以内就会崩溃。
3.2安全写法1使用互斥量QMutex.并使用lock)和unlock0方法进行锁定和解锁,但这个方法难以对返回参数进行保护
3.2安全写法2使用互斥量QMutex,并使用QMutexLocker 进行锁定,当QMutexLocker从栈释放后,自动解锁
3.3安全写法3使用读写锁 QReadWriteLock,并使用 lockForRead0和lockForWrite)对读或写进行保护,这种方法相比QMutex效率更高,因为它允许多线程同时读。
3.4更多保证类的线程安全性的办法
1.使用生产者一消费者模式,通过缓冲区产生多个数据的备份,可提高线程间数据共享的效率
2.使用socket进行线程间,甚至进程间的数据共享3.类不提供访问实例中成员的方法,而是通过信号槽机制,进行线程间的数据共享