當前位置:首頁 » 操作系統 » linux線程安全

linux線程安全

發布時間: 2022-04-27 11:38:42

1. linuxC++如何編寫線程安全庫

LinuxC++編寫線程安全庫dll的方法:
1、動態庫只有一個導出函數。
這種情況下編寫函數時,只需要考慮不要有沖突的全局數據就可以了。這里的全局數據包括了在堆中分配的數據塊和靜態全局變數等。如果存在這樣的全局數據,那麼進程中的不同線程訪問這個函數就會造成沖突。
2、動態庫導出了多個函數,而且多個函數間存在數據傳遞。
一般DLL都導出多個函數,一個初始化,一個資源釋放,其他為核心功能函數。這些函數間極有可能發生數據傳遞。如果一個初始化函數是在線程A中調用的,而核心功能函數是在線程B中調用的,那麼線程A初始化函數的資源就無法對應線程B中的核心功能,此外還有核心功能函數間的數據傳遞,這樣的DLL就不是線程安全的,必然導致錯誤。
解決辦法是由用戶(即使用DLL的人)保證這些導出函數是在一個線程中調用。但這樣會很大程度上限制介面的設計和用戶的使用自由度。所以最好的方法是函數只管自己的線程安全,不同函數傳遞數據用動態TLS,線程局部存儲
3、限制訪問DLL中某一函數的線程數目。
對於DLL中的某一個函數的訪問線程數目是有限制的,超過了限制其他線程就得等一定的時間,一定的時間過後如果還不能得到執行機會,那就返回超時。這樣的設計對用戶來說是友好的,而且很實用,有的商業程序確實是按照允許用戶訪問的通道數目來計價的。
對DLL中的函數做這樣的一個封裝,一般是簡單的待用Semaphore信號量,來解決。DLL初始化時調用CreateSemaphore函數對信號量進行初始化,其原型如下:
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
// pointer to security attributes
LONG lInitialCount, // initial count
LONG lMaximumCount, // maximum count
LPCTSTR lpName // pointer to semaphore-object name
);
對於信號量,它每WaitForSingleObject一次(當然是要進入),其狀態值(一個整數)就減1,使用完ReleaseSemaphore其狀態值就加1,當其狀態值為0時信號量就由有信號變為無信號。利用信號量的這一特性,我們在初始化時將信號量的初始值(第2個參數)設置為限制的線程訪問數目。在要限制訪問線程數目的函數內部,通過調用WaitForSingleOject獲取控制權,並指定一個等待時間(這個由配置文件指定),根據情況超時返回,使用完ReleaseSemaphore釋放對佔用,讓其他線程可以調用這個函數。
4、多進程情況下的多線程安全DLL。
LL是可以被多個進行載入並調用的。那就是說如果我們只對一個進程進行了限制,那麼在多進程調用的情況下,這樣的限制被輕易攻破。
我們都知道,Semaphore信號量屬於內核對象,也就是說其可以被多進程共享訪問,也就說,如果我們給一個Semaphore指定了一個名字,在另一個進程中,我們只要調用OpenSemaphore函數用同一名字打開信號量就可以訪問了。這樣問題就解決了?
現實情況是,多進程情況下,一般不是簡單的多進程共享一個Semaphore就可以了。多進程間需要互通很多信息。一般的解決辦法是,採用共享數據段。
#pragma data_seg("share")
int share_data;
#pragma data_seg()
#pragma comment(linker,"/SECTION:share, RWS")
通過pragam編譯器指令生成了一個名叫share的共享數據段,這樣對於變數share_data就可以多進程共享的了。如果要多進程間交換數據,只要在data_seg中添加數據定義即可。

2. linux open線程安全嗎

應該是安全的: time_t mktime(struct tm *tm); 輸入的tm結構不要在多個線程中同時被調用mktime應該就沒有問題

3. linux g++ 的stl是線程安全的么

STL的線程安全問題不能一概而論,從標准上說,STL從來沒說過自己是線程安全的,同時為了性能,很多地方也無法實現線程安全(要完美實現線程安全必須產生大量的臨界鎖定,會大大影響性能),所以首先你應該認為stl不是線程安全的,並且盡量依靠自己來做線程同步安全機制。
但STL在一定程度上可以看做是線程安全
1:多線程讀是安全的,多線程寫是不安全的
2:不同容器的多線程讀寫是沒問題的,同一個容器不能多線程寫
3:返回迭代器的時候,迭代器的生命周期內一定要自己做安全同步

4. linux fputs是不是線程安全

是線程安全的。可以查看手冊,裡面寫是了線程安全的。

5. 有人能教下我有關linux裡面線程的知識嗎

.線程的基本介紹
(1)線程的概述
線程與進程類似,也允許應用程序並發執行多個任務的一種機制。一個進程可以包含多個線程,同一程序中的所有線程共享同一份全局內存區域,線程之間沒有真正意義的等級之分。同一個進程中的線程可以並發執行,如果處理器是多核的話線程也可以並行執行,如果一個線程因為等待I/O操作而阻塞,那麼其他線程依然可以繼續運行
(2)線程優於進程的方面

argv,environ

主線程棧
線程3的棧
線程2的棧
線程1的棧
共享函數庫共享的內存

未初始化的數據段
初始化數據段
文本
.進程間的信息難以共享。由於除去只讀代碼段外,父子進程並未共享內存,因此必須採用一些進程間通訊,在進程之間交換信息
.調用fork()來創建進程代價相對較高
線程很好的解決了上述倆個問題
.線程之間能夠方便,快速的共享信息,只需將數據復制到共享(全局或堆)變數中即可
.創建線程比創建線程通常要快10甚至更多,線程創建之所以快,是因為fork創建進程時所需復制多個屬性,而在線程中,這些屬性是共享的。
(3)創建線程
啟動程序時,產生的進程只有單條線程,我們稱之為主線程
#include<pthread.h>
int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void*(*start)(void *),void *arg);12

新線程通過調用帶有arg的函數開始執行,調用pthread_create()的線程會繼續執行該調用之後的語句。
(4)終止線程
可以以如下方式終止線程的運行
.線程調用pthread_exit()
.線程start函數執行return語句並返回指定值
.調用pthread_cancel()取消線程
.任意線程調用了exit(),或者主線程執行了return語句,都會導致進程中的所有線程立即終止
pthread_exit()函數可以終止線程,且其返回值可由另一線程通過調用pthread_join()獲得
#include<pthread.h>void pthread_exit(void *retval);12

調用pthread_exit()相當於在線程的start函數中執行return,不同之處在於,pthread_exit()可以在任何地方調用,參數retval指定了線程的返回值
(5)獲取線程ID
#include<pthread.h>pthread_t pthread_self(void);12

線程ID在應用程序中主要有如下用途
.不同的pthreads函數利用線程ID來標識要操作目標線程。
.在具體的應用程序中,以特定線程的線程ID作為動態數據結構的標簽,這頗有用處,既可用來識別某個數據結構的創建者或屬主線程,又可確定隨後對該數據結構執行操作的具體線程
函數pthread_equal()可檢查倆個線程的ID是否相同
#include<pthread.h>int pthread_equal(pthread_t t1,pthread_t t2);//如果相同返回非0值,否則返回0123

(6)連接已終止的線程
函數pthread_join()等待由thread表識的線程終止
#include<pthread.h>int pthread_join(pthread_t thread,void **retval);//返回0調用成功,否則失敗123

如果pthread_join()傳入一個之前已然連接過的線程ID,將會導致無法預知的行為,當相同線程ID在參與一次連接後恰好為另一新建線程所重用,再度連接的可能就是這個新線程
若線程未分離,則就應該使用pthread_join()來連接線程,否則會產生僵屍線程
pthrea_join()函數的要點
.線程之間的關系是對等的,所以任意線程都可以調用pthread_join()來連接其他線程
.pthread_join()無法針對任意線程,只能連接單個線程
(6)線程的分離
默認情況下線程都是可連接的,但有時候,我們並不關心線程退出的狀態,我們可以調用pthread_detach()並向thread參數傳入指定線程的的標識符,將該線程標記為處於分離狀態
#include<pthread.h>int pthread_detach(pthread_t thread);//返回0成功,否則失敗123

一旦線程處於分離狀態,就不能在使用pthread_join()來獲取其狀態,也無法使其重返可連接狀態
(7)在應用程序中如何來選擇進程還是線程
.線程之間共享數據很簡單,進程間的數據共享需要更多的投入
.創建線程要比創建進程塊很多
.多線程編程時,需要確保調用線程安全的函數
.某個線程中的bug可能會危害進程中所有線程
.每個線程都在徵用宿主進程中有限的虛擬地址空間
.在多線程應用中,需要小心使用信號
.除了數據,線程還可以共享文件描述符,信號處置,當前工作目錄,以及用戶ID和組ID
線程的同步
(1)保護共享變數訪問:互斥量
線程的主要優勢在於能夠通過全局變數來共享信息,不過這種共享是有代價的。必須確保多個線程修改同一變數時,不會有其他線程也正在修改此變數,為避免線程更新時共享變數時所出現的問題,必須使用互斥量來確保同時僅有一個線程可以訪問某項共享資源
(2)靜態分配的互斥鎖
互斥鎖既可以像靜態變數那樣分配,也可以在運行時動態分配,互斥量屬於pthread_mutex_t類型的變數,在使用之前必須對其初始化。對於靜態分配的互斥量而言,可如下例所示,將PTHREAD_MUTEX_INITIALIZER賦給互斥量
pthread_mutex_t = PTHREAD_MUTEX_INITIALIZER;1

1.加鎖和解鎖互斥量
初始化之後,互斥量處於未鎖定狀態。函數pthread_mutex_lock()可以鎖定某一互斥量
而函數pthread_mutex_unlock()則可以將一個互斥量解鎖
#include<pthread.h>int pthread_mutex_lock(pthread_mutex_t *mutex);int pthread_mutex_unlock(pthread_mutex_t *mutex);//返回0成功,其他失敗1234

要鎖定互斥量,在調用pthread_mutex_lock()時需要指定互斥量,如果互斥量當前處於未鎖定狀態,則該調用將會立即返回,如果該互斥量已被其他線程鎖定,那麼該調用將會阻塞,直至互斥量被解鎖
函數pthread_mutex_unlock()將解鎖之前已遭調用線程鎖定的互斥量
2.互斥量的性能
通常情況下,線程會花費更多的時間去做其他工作,對互斥量的加鎖解鎖相對要少的多,因此使用互斥量對大部分程序來說性能並無顯著的影響
3.互斥量的死鎖
當一個線程需要同時訪問多個共享資源時,沒個資源由不同的互斥索管理。當超過一個線程加鎖同一組互斥量時,就有可能發生死鎖。如下圖所示
線程A
1.pthread_mutex_lock(mutex1);
2.pthread_mutex_lock(mutex2);
線程2
1.pthread_mutex_lock(mutex2);
2.pthread_mutex_lock(mutex1);
每個線程都成功的鎖住一個互斥量,接著試圖對以為另一線程鎖定的互斥量加鎖,就會一直等下去
要避免此類死鎖問題,最簡單的就是定義互斥量的層級關系

6. linux的mv命令是線程安全的嗎

多線程退出有三種方式:
(1)執行完成後隱式退出;

(2)由線程本身顯示調用pthread_exit 函數退出;
pthread_exit (void * retval) ;

(3)被其他線程用pthread_cance函數終止:
pthread_cance (pthread_t thread) ;

用event來實現。

在子線程中,在循環內檢測event。
while(!e.is_active())
{
...
}
當退出循環體的時候,自然return返回。這樣子線程會優雅的結束。
注意:選用非等待的檢測函數。

pthread 線程有兩種狀態,joinable(非分離)狀態和detachable(分離)狀態,默認為joinable。

joinable:當線程函數自己返回退出或pthread_exit時都不會釋放線程所用資源,包括棧,線程描述符等(有人說有8k多,未經驗證)。

detachable:線程結束時會自動釋放資源。

Linux man page said:

When a joinable thread terminates, its memory resources (thread descriptor and stack) are not deallocated until another thread performs pthread_join on it. Therefore, pthread_join must be called once for each joinable thread created to avoid memory leaks.

因此,joinable 線程執行完後不使用pthread_join的話就會造成內存泄漏。

解決辦法:

1.// 創建線程前設置 PTHREAD_CREATE_DETACHED 屬性

pthread_attr_t attr;
pthread_t thread;
pthread_attr_init (&attr);
pthread_attr_setdetachstat(&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&thread, &attr, &thread_function, NULL);
pthread_attr_destroy (&attr);

2.當線程為joinable時,使用pthread_join來獲取線程返回值,並釋放資源。

3.當線程為joinable時,也可在線程中調用 pthread_detach(pthread_self());來分離自己。

7. 保證線程安全的方法

線程(Thread),有時被稱為輕量級進程(LWP),是程序執行流的最小單位;一個標準的線程由線程ID、當前指令指針(PC)、寄存器集合和堆棧組成。通常情況下,一個進程由一個到多個線程組成,各個線程之間共享程序的內存空間及一些進程級的資源。

在大多數軟體應用中,線程的數量都不止一個,多線程程序處在一個多變的環境中,可訪問的全局變數和堆數據隨時都可能被其他的線程改變,這就將「線程安全」的問題提上了議程。那麼,如何確保線程的安全呢?

線程安全
一般說來,確保線程安全的方法有這幾個:競爭與原子操作、同步與鎖、可重入、過度優化。

競爭與原子操作
多個線程同時訪問和修改一個數據,可能造成很嚴重的後果。出現嚴重後果的原因是很多操作被操作系統編譯為匯編代碼之後不止一條指令,因此在執行的時候可能執行了一半就被調度系統打斷了而去執行別的代碼了。一般將單指令的操作稱為原子的(Atomic),因為不管怎樣,單條指令的執行是不會被打斷的。

因此,為了避免出現多線程操作數據的出現異常,Linux系統提供了一些常用操作的原子指令,確保了線程的安全。但是,它們只適用於比較簡單的場合,在復雜的情況下就要選用其他的方法了。

同步與鎖
為了避免多個線程同時讀寫一個數據而產生不可預料的後果,開發人員要將各個線程對同一個數據的訪問同步,也就是說,在一個線程訪問數據未結束的時候,其他線程不得對同一個數據進行訪問。

同步的最常用的方法是使用鎖(Lock),它是一種非強制機制,每個線程在訪問數據或資源之前首先試圖獲取鎖,並在訪問結束之後釋放鎖;在鎖已經被佔用的時候試圖獲取鎖時,線程會等待,直到鎖重新可用。

二元信號量是最簡單的一種鎖,它只有兩種狀態:佔用與非佔用,它適合只能被唯一一個線程獨占訪問的資源。對於允許多個線程並發訪問的資源,要使用多元信號量(簡稱信號量)。

可重入
一個函數被重入,表示這個函數沒有執行完成,但由於外部因素或內部因素,又一次進入該函數執行。一個函數稱為可重入的,表明該函數被重入之後不會產生任何不良後果。可重入是並發安全的強力保障,一個可重入的函數可以在多線程環境下放心使用。

過度優化
在很多情況下,即使我們合理地使用了鎖,也不一定能夠保證線程安全,因此,我們可能對代碼進行過度的優化以確保線程安全。

我們可以使用volatile關鍵字試圖阻止過度優化,它可以做兩件事:第一,阻止編譯器為了提高速度將一個變數緩存到寄存器而不寫回;第二,阻止編譯器調整操作volatile變數的指令順序。

在另一種情況下,CPU的亂序執行讓多線程安全保障的努力變得很困難,通常的解決辦法是調用CPU提供的一條常被稱作barrier的指令,它會阻止CPU將該指令之前的指令交換到barrier之後,反之亦然。

8. linux 消息隊列 線程安全嗎

yes
IPC都是可重入的

在linux下可以使用info libc看看吧

9. linux 消息隊列線程安全嗎

安全!消息隊列是消息的鏈表,存放在內核中並有消息隊列標示符標示。

熱點內容
西門吹雪腳本 發布:2024-10-04 06:54:42 瀏覽:954
android電子相冊 發布:2024-10-04 06:49:41 瀏覽:998
phpapp第三方登錄介面 發布:2024-10-04 06:40:02 瀏覽:748
Lgc的演算法 發布:2024-10-04 06:35:23 瀏覽:857
華為安卓70彩蛋怎麼 發布:2024-10-04 06:17:32 瀏覽:438
谷歌和安卓什麼關系 發布:2024-10-04 06:16:57 瀏覽:380
伺服器形式的電腦 發布:2024-10-04 06:08:35 瀏覽:819
python中的for函數 發布:2024-10-04 05:51:33 瀏覽:308
裝linux系統的電腦 發布:2024-10-04 05:24:36 瀏覽:561
維修案例資料庫 發布:2024-10-04 05:23:02 瀏覽:982