新聞中心
在多線程編程中,共享資源的訪問往往會(huì)引發(fā)競爭條件,而競爭條件會(huì)導(dǎo)致數(shù)據(jù)不一致或程序崩潰等問題。為了避免這種情況的發(fā)生,需要使用原子操作函數(shù)來控制和同步對(duì)共享資源的訪問。本文將為您介紹Linux中的原子操作函數(shù)以及如何使用這些函數(shù)來保護(hù)共享資源。

創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的常德網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
1. 什么是原子操作?
原子操作是指在多線程編程中,一個(gè)操作要么完全執(zhí)行,要么完全不執(zhí)行,不存在中途被打斷或修改的情況。在高并發(fā)環(huán)境下,原子操作可以避免競爭條件的發(fā)生,確保數(shù)據(jù)的一致性和程序的正確性。
在Linux中,原子操作是通過內(nèi)聯(lián)匯編語句來實(shí)現(xiàn)的。內(nèi)聯(lián)匯編語句可以直接嵌入到C/C++代碼中,使得代碼執(zhí)行更快,更高效。
2. Linux中的原子操作函數(shù)
Linux提供了一系列的原子操作函數(shù)來控制共享資源的訪問,包括:
(1)atomic_t類型和atomic_set()/atomic_read()函數(shù)
atomic_t類型是Linux中表示原子變量的數(shù)據(jù)類型。它是一個(gè)32位的有符號(hào)整數(shù),可以使用atomic_set()和atomic_read()函數(shù)來設(shè)置和讀取它的值。atomic_set()函數(shù)可以將atomic_t類型變量設(shè)置為指定的值,而atomic_read()函數(shù)可以讀取atomic_t類型變量的當(dāng)前值。
(2)atomic_add()/atomic_sub()函數(shù)
atomic_add()和atomic_sub()函數(shù)可以分別對(duì)atomic_t類型變量進(jìn)行加法和減法操作。它們可以在保持原子性的同時(shí),改變atomic_t類型變量的值。
(3)atomic_inc()/atomic_dec()函數(shù)
atomic_inc()和atomic_dec()函數(shù)可以分別實(shí)現(xiàn)對(duì)atomic_t類型變量的加1和減1操作。它們可以在保持原子性的同時(shí),改變atomic_t類型變量的值。這些函數(shù)通常用于實(shí)現(xiàn)計(jì)數(shù)器或引用計(jì)數(shù)器。
(4)atomic_add_return()/atomic_sub_return()函數(shù)
atomic_add_return()和atomic_sub_return()函數(shù)可以分別實(shí)現(xiàn)對(duì)atomic_t類型變量的加法和減法操作,并返回操作后的新值。它們可以在保持原子性的同時(shí),改變atomic_t類型變量的值,并且返回操作后的新值。
(5)atomic_inc_return()/atomic_dec_return()函數(shù)
atomic_inc_return()和atomic_dec_return()函數(shù)可以分別實(shí)現(xiàn)對(duì)atomic_t類型變量的加1和減1操作,并返回操作后的新值。它們可以在保持原子性的同時(shí),改變atomic_t類型變量的值,并且返回操作后的新值。這些函數(shù)通常用于實(shí)現(xiàn)計(jì)數(shù)器或引用計(jì)數(shù)器。
(6)atomic_cmpxchg()函數(shù)
atomic_cmpxchg()函數(shù)可以實(shí)現(xiàn)原子級(jí)比較和交換操作。它將比較一個(gè)指定的atomic_t類型變量和一個(gè)期望的值,如果兩個(gè)值相等,則將atomic_t類型變量設(shè)置為一個(gè)新值,并返回原來的值。它可以有效地解決競爭條件問題,確保數(shù)據(jù)的一致性和程序的正確性。
3. 如何使用原子操作函數(shù)?
在使用原子操作函數(shù)之前,我們需要了解一些基本原則和使用方式:
(1)盡量減少共享資源的使用,避免多個(gè)線程同時(shí)訪問同一共享資源。如果必須使用共享資源,需要使用原子操作函數(shù)來控制訪問。
(2)使用atomic_t類型來定義共享資源,避免使用普通的數(shù)據(jù)類型。
(3)為了避免不必要的競爭條件,應(yīng)該盡量將原子操作函數(shù)放在代碼的關(guān)鍵部分或者最小代碼范圍內(nèi)。
(4)要保證原子操作的正確性和可靠性,需要使用適當(dāng)?shù)耐綑C(jī)制來協(xié)調(diào)多個(gè)線程之間的操作。例如,可以使用互斥鎖或信號(hào)量來解決并發(fā)訪問共享資源的問題。
下面是一個(gè)例子,展示了如何使用atomic_t類型和原子操作函數(shù)來控制對(duì)共享資源的訪問:
“`
#include
#include
#include
MODULE_LICENSE(“Dual BSD/GPL”);
static atomic_t counter = ATOMIC_INIT(0);
static int __init atomic_example_init(void)
{
printk(KERN_INFO “Atomic Example Init\n”);
atomic_inc(&counter);
printk(KERN_INFO “Counter Value: %d\n”, atomic_read(&counter));
return 0;
}
static void __exit atomic_example_exit(void)
{
printk(KERN_INFO “Atomic Example Exit\n”);
}
module_init(atomic_example_init);
module_exit(atomic_example_exit);
“`
在這個(gè)例子中,我們定義了一個(gè)atomic_t類型的變量counter,并使用ATOMIC_INIT宏將其初始化為0。在模塊加載時(shí),我們使用atomic_inc()函數(shù)對(duì)counter進(jìn)行加1操作,并使用atomic_read()函數(shù)打印counter的值。在模塊卸載時(shí),我們打印一條退出消息。
4.
相關(guān)問題拓展閱讀:
- sig_atomic_t的Linux內(nèi)核中的原子操作 atomic_t
- Linux 多線程編程(二)
sig_atomic_t的Linux內(nèi)核中的原子操作 atomic_t
原型:
typedef struct {
volatile int counter;
} atomic_t;
1 聲明,定義并初始化原子變量
atomic_t isopen = ATOMIC_INIT(1);
2 使用方法隱汪
原子變量自減1,并測(cè)試是否灶蠢仔為0,如果為0,返回true,否則返回false
if( !atomic_dec_and_test(&isopen) ) {
atomic_inc(&isopen); //加1操作
return -EBUSY;
}
3 釋檔租放
減1操作
atomic_dec(&isopen);
Linux 多線程編程(二)
三種專門用于線程同步的機(jī)制:POSIX信號(hào)量,互斥量和條件變量.
在Linux上信號(hào)量API有兩組,一組是System V IPC信號(hào)量,即PV操作,另外就是POSIX信號(hào)量,POSIX信號(hào)量的名字都是以sem_開頭.
phshared參數(shù)指定信號(hào)量的類型,若其值為0,就表示這個(gè)信號(hào)量是當(dāng)前進(jìn)程的局部信號(hào)量,否則該信號(hào)量可以在多個(gè)進(jìn)程之間共享.value值指定信號(hào)量的初始值,一般與下面的sem_wait函數(shù)相對(duì)應(yīng).
其中比較重要的函數(shù)sem_wait函數(shù)會(huì)以原子操作的方式將信號(hào)量的值減一,如果信號(hào)量的值為零,則sem_wait將會(huì)阻塞,信號(hào)量的值可以在sem_init函數(shù)中的value初始化;sem_trywait函數(shù)是sem_wait的非阻塞版本;sem_post函數(shù)將以原子的操作對(duì)信號(hào)量加一,當(dāng)信號(hào)量的值大于0時(shí),其他正在調(diào)用sem_wait等待信號(hào)量的線程將被喚醒.
這些函數(shù)成功時(shí)返回0,失敗則返回-1并設(shè)置errno.
生產(chǎn)者消費(fèi)者模型:
生產(chǎn)者對(duì)應(yīng)一個(gè)信號(hào)量:sem_t producer;
消費(fèi)者對(duì)應(yīng)一個(gè)信號(hào)量:sem_t customer;
sem_init(&producer,2)—-生產(chǎn)者擁有資源,可以工悶亂作;
sem_init(&customer,0)—-消費(fèi)者沒有資源,阻塞;
在訪問公共資源前對(duì)互滾耐斥量設(shè)置(加鎖),確保同一時(shí)間只有一個(gè)線程訪問數(shù)據(jù),在訪問完成后再釋放(解鎖)互斥量.
互斥鎖的運(yùn)行方式:串行訪問共享資源;
信號(hào)量的運(yùn)行方式:并行訪問共享資源;
互斥量用pthread_mutex_t數(shù)據(jù)類型表示,在使用互斥量之前,必須使用pthread_mutex_init函數(shù)對(duì)它進(jìn)行初始化,注意,使用完畢后需調(diào)用pthread_mutex_destroy.
pthread_mutex_init用于初始化互斥鎖,mutexattr用于指定互斥鎖的屬性,若為NULL,則表示默認(rèn)屬性。除了用這個(gè)函數(shù)初始化互斥所外,還可以用如下方式初始化:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER。
pthread_mutex_destroy用于銷毀互斥鎖,以釋放占用的內(nèi)核資源,銷毀一個(gè)已經(jīng)加鎖的互斥鎖將導(dǎo)致不可預(yù)期的后果。
pthread_mutex_lock以原子操作給一個(gè)互斥鎖加鎖。如果目標(biāo)互斥鎖已經(jīng)被加鎖,則pthread_mutex_lock則被阻塞,直到該互斥鎖占有者把它給解鎖.
pthread_mutex_trylock和pthread_mutex_lock類似,不過它始終立即返回,而不論作的互斥鎖是否加鎖,是pthread_mutex_lock的非阻塞版本.當(dāng)目標(biāo)互斥鎖未被加鎖時(shí),pthread_mutex_trylock進(jìn)行加鎖操作;否則將返回EBUSY錯(cuò)誤碼。注意:這里討論的pthread_mutex_lock和pthread_mutex_trylock是針對(duì)普通鎖而言的,對(duì)于其他類型的鎖,這兩個(gè)加鎖函數(shù)會(huì)有不同的行為.
pthread_mutex_unlock以原子操作方式給一個(gè)互斥鎖進(jìn)行解鎖操作。如果此時(shí)有其他線程正在等待這個(gè)互斥鎖,則這些線程中的一個(gè)將獲得它.
三個(gè)打印機(jī)輪流打印:
輸出結(jié)螞備檔果:
如果說互斥鎖是用于同步線程對(duì)共享數(shù)據(jù)的訪問的話,那么條件變量就是用于在線程之間同步共享數(shù)據(jù)的值.條件變量提供了一種線程之間通信的機(jī)制:當(dāng)某個(gè)共享數(shù)據(jù)達(dá)到某個(gè)值時(shí),喚醒等待這個(gè)共享數(shù)據(jù)的線程.
條件變量會(huì)在條件不滿足的情況下阻塞線程.且條件變量和互斥量一起使用,允許線程以無競爭的方式等待特定的條件發(fā)生.
其中pthread_cond_broadcast函數(shù)以廣播的形式喚醒所有等待目標(biāo)條件變量的線程,pthread_cond_signal函數(shù)用于喚醒一個(gè)等待目標(biāo)條件變量線程.但有時(shí)候我們可能需要喚醒一個(gè)固定的線程,可以通過間接的方法實(shí)現(xiàn):定義一個(gè)能夠唯一標(biāo)識(shí)目標(biāo)線程的全局變量,在喚醒等待條件變量的線程前先設(shè)置該變量為目標(biāo)線程,然后采用廣播的方式喚醒所有等待的線程,這些線程被喚醒之后都檢查該變量以判斷是否是自己.
采用條件變量+互斥鎖實(shí)現(xiàn)生產(chǎn)者消費(fèi)者模型:
運(yùn)行結(jié)果:
阻塞隊(duì)列+生產(chǎn)者消費(fèi)者
運(yùn)行結(jié)果:
linux 原子操作函數(shù)的介紹就聊到這里吧,感謝你花時(shí)間閱讀本站內(nèi)容,更多關(guān)于linux 原子操作函數(shù),Linux中的原子操作函數(shù):快速高效地控制共享資源,sig_atomic_t的Linux內(nèi)核中的原子操作 atomic_t,Linux 多線程編程(二)的信息別忘了在本站進(jìn)行查找喔。
成都網(wǎng)站設(shè)計(jì)制作選創(chuàng)新互聯(lián),專業(yè)網(wǎng)站建設(shè)公司。
成都創(chuàng)新互聯(lián)10余年專注成都高端網(wǎng)站建設(shè)定制開發(fā)服務(wù),為客戶提供專業(yè)的成都網(wǎng)站制作,成都網(wǎng)頁設(shè)計(jì),成都網(wǎng)站設(shè)計(jì)服務(wù);成都創(chuàng)新互聯(lián)服務(wù)內(nèi)容包含成都網(wǎng)站建設(shè),小程序開發(fā),營銷網(wǎng)站建設(shè),網(wǎng)站改版,服務(wù)器托管租用等互聯(lián)網(wǎng)服務(wù)。
新聞名稱:Linux中的原子操作函數(shù):快速高效地控制共享資源 (linux 原子操作函數(shù))
網(wǎng)址分享:http://m.5511xx.com/article/djcdsoc.html


咨詢
建站咨詢
