国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C++并發(fā)線程 - 如何線程間共享數(shù)據(jù)【詳解:如何使用鎖操作】

這篇具有很好參考價(jià)值的文章主要介紹了C++并發(fā)線程 - 如何線程間共享數(shù)據(jù)【詳解:如何使用鎖操作】。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

系列文章目錄

點(diǎn)擊進(jìn)入系列文章目錄
C++技能系列
Linux通信架構(gòu)系列
C++高性能優(yōu)化編程系列
深入理解軟件架構(gòu)設(shè)計(jì)系列
高級(jí)C++并發(fā)線程編程

期待你的關(guān)注哦?。。?/strong>
C++并發(fā)線程 - 如何線程間共享數(shù)據(jù)【詳解:如何使用鎖操作】

快樂在于態(tài)度,成功在于細(xì)節(jié),命運(yùn)在于習(xí)慣。
Happiness lies in the attitude, success lies in details, fate is a habit.


具體哪個(gè)線程按何種方式訪問什么數(shù)據(jù)?還有,一旦改動(dòng)了數(shù)據(jù),如果牽涉到其他線程,它們要在何時(shí)以什么通信方式獲得通知?同一進(jìn)程內(nèi)的多個(gè)線程之間,雖然可以簡(jiǎn)單易行地共享數(shù)據(jù),但這不是絕對(duì)的優(yōu)勢(shì),優(yōu)勢(shì)甚至是很大的劣勢(shì)。不正確使用共享數(shù)據(jù),是產(chǎn)生與開發(fā)有關(guān)的錯(cuò)誤的一個(gè)很大的誘因。

如果共享數(shù)據(jù)都是只讀數(shù)據(jù),就不會(huì)有問題;但是,同時(shí)一旦有刪除刪除數(shù)據(jù)就會(huì)出現(xiàn)問題。

在并發(fā)編程中,操作由兩個(gè)或者多個(gè)線程負(fù)責(zé),它們爭(zhēng)先讓線程執(zhí)行各自的操作,而結(jié)果取決于它們執(zhí)行的相對(duì)次序,所有這種情況都是條件競(jìng)爭(zhēng)。

1、但是如何防止惡性的條件競(jìng)爭(zhēng)呢?

  • 有鎖數(shù)據(jù)結(jié)構(gòu):采取保護(hù)措施包裝數(shù)據(jù)結(jié)構(gòu),確保不變量被破壞時(shí),中間狀態(tài)只對(duì)執(zhí)行改動(dòng)線程可見。在其他訪問同一數(shù)據(jù)結(jié)構(gòu)的視角中,這種改動(dòng)要么尚未開始,要么已經(jīng)完成。
  • 無鎖數(shù)據(jù)結(jié)構(gòu):修改數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì)及其不變量,由一連串不可拆分的改動(dòng)完成數(shù)據(jù)變更,每個(gè)改動(dòng)都維持?jǐn)?shù)據(jù)變量不被破壞。通常這種編程難以正確編寫。

保護(hù)共享數(shù)據(jù)的最基本方式就是互斥。

2、如何用互斥保護(hù)共享數(shù)據(jù)?

訪問一個(gè)數(shù)據(jù)結(jié)構(gòu)前,先鎖住與數(shù)據(jù)相關(guān)的互斥;訪問結(jié)束后,再解鎖互斥。C++線程庫保證了,一旦有線程鎖住了某個(gè)互斥,若其他線程試圖再給它加鎖,則須等待,直至最初成功加鎖的線程把該互斥解鎖。這確保了全部線程所見到的共享數(shù)據(jù)是正確的,不變量沒有沒有被破壞。

2.1 如何使用互斥?

通過 std::mutex的實(shí)例創(chuàng)建互斥,調(diào)用成員函數(shù)lock()對(duì)其加鎖,調(diào)用unlock()解鎖。但是一般不推薦直接調(diào)用成員函數(shù)的做法。原因是若按此處理,那就必須記住,在函數(shù)以外的每條代碼路徑上都要調(diào)用unlock(),包括由于異常導(dǎo)致退出的路徑。

C++標(biāo)準(zhǔn)庫提供了類模版std::lock_guard<>,針對(duì)互斥融合實(shí)現(xiàn)了RAII機(jī)制:在構(gòu)造是給互斥加鎖,在析構(gòu)時(shí)給互斥解鎖,從而保證互斥總被正確的解鎖。

如下,用互斥保護(hù)鏈表:

#include <list>
#include <mutex>
#include <algorithm>
std::list<int> some_list;
void add_to_list(int new_value)
{
	std::lock_guard<std::mutex> guard(some_mutex);
	some_list.push_back(new_value);
}
bool list_contains(int value_to_find)
{
	std::lock_gurd<std::mutex> guard(some_mutex);
	return std::find(some_list.begin(), some_list.end(), value_to_find) != some_list.end();
}

2.2 本意互斥保護(hù)數(shù)據(jù)卻留有余地,如何防止隱患呢?

如果成員函數(shù)返回的指針或者引用,指向受保護(hù)的共享數(shù)據(jù),那么即便成員函數(shù)全都良好、有序的方式鎖定互斥,仍然無濟(jì)于事,因?yàn)槭鼙Wo(hù)已被打破,出現(xiàn)大漏洞。 只要存在任何能訪問該指針和引用的代碼,它就可以訪問受保護(hù)的共享數(shù)據(jù),則須謹(jǐn)慎設(shè)計(jì)程序接口,從而確?;コ庀刃墟i定,再對(duì)受保護(hù)的共享數(shù)據(jù)進(jìn)行訪問,并保證不留后門。

我們來看看,意外的向外傳遞引用,指向受保護(hù)的共享數(shù)據(jù):

class some_data
{
	int a;
	std::string b;
public:
	void do_something();
};
class data_wrapper
{
private:
	some_data data;
	std::mutex m;
public:
	template<typename Fubction>
	void process_data(Function func)
	{
		std::lock_guard<std::mutex> l(m);
		//向使用者提供的函數(shù)傳遞受保護(hù)的數(shù)據(jù)
		func(data);
	}
};
some_data* unprotected;
void malicious_function(some_data& protected_data)
{
	unprotected = &protected_data;
}
data_wrapper x;
void foo()
{
	//傳入惡意函數(shù)
	x.process_data(malicious_function);
	//以無保護(hù)方式訪問本應(yīng)受保護(hù)的共享數(shù)據(jù)
	unprotected->do_something();
}

我們除了要檢查成員函數(shù),防止向調(diào)用者傳出指針或引用,還必須檢查另一種情況:若成員函數(shù)在自身內(nèi)部調(diào)用了別的函數(shù),而這些函數(shù)卻不受我們掌控,那么,也不得向他們傳遞這些指針或引用。如果有就很危險(xiǎn)。

2.3 如何解決容器本身接口固有的條件競(jìng)爭(zhēng)?

多線程訪問的情況下STL容器內(nèi)的empty()size()的結(jié)果不可信。盡管,在某個(gè)線程調(diào)用empty()size()時(shí),返回值可能是正確的。然而,一旦函數(shù)返回,其他線程就不再受限,從而能自由地訪問棧容器,可能馬上有新元素入棧,或者,現(xiàn)有的元素會(huì)立刻出棧,令前面的線程得到結(jié)果失效而無法使用。

在空棧上調(diào)用top()會(huì)導(dǎo)致未定義行為。

但是如何解決上述問題?

  • 傳入引用;
  • 提供不拋出異常的拷貝構(gòu)造函數(shù)或不拋出異常的移動(dòng)構(gòu)造函數(shù);
  • 返回指針指向彈出的元素。

如下代碼,線程安全的棧容器類:

#include <exception>
#include <memory>
#include <mutex>
#include <stack>
struct empty_stack: std::exception
{
	const char* what() const throw();
};
template<typename T>
class threadsafe_stack
{
private:
	std::statck<T> data;
	mutable std::mutex m;
public:
	threadsafe_stack(){}
	threadsafe_stack(const threadsafe_stack& other)
	{
		std::lock_guard<std::metux> lock(other.m);
		//在構(gòu)造函數(shù)的函數(shù)體(constructor body)內(nèi)進(jìn)行復(fù)制操作
		data = other.data;
	}
	//將賦值運(yùn)算符刪除
	threadsafe_stack& operator=(const threadsafe_stack&) = delete;
	void push(T new_value)
	{
		std::lock_guard<std::mutex> lock(m);
		data.push(std::move(new_value));
	}
	//返回std::share_ptr<T>
	std::share_ptr<T> pop()
	{
		std::lock_guard<std::mutex> lock(m);
		//試圖在彈出前檢查是否為空棧
		if(data.empty()) throw empty_stack();
		//改動(dòng)棧容器前設(shè)置返回值
		std::share_ptr<T> const res(std::make_shared<T>(data.top()));
		data.pop();
		return res;
	}
	//接收引用參數(shù),指向某外部變量的地址,存儲(chǔ)彈出的值
	void pop(T& value)
	{
		std::lock_guard<std::mutex> lock(m);
		if(data.empty()) throw empty_stack();
		value = data.top();
		data.pop();
	}
	bool empty() const
	{
		std::lock_guard<std::mutex> lock(m);
		return data.empty();
	}
};

2.4 如何解決死鎖問題?

線程在互斥上爭(zhēng)奪搶鎖:有兩個(gè)線程,都需同時(shí)鎖住兩個(gè)互斥,都等待著再給另一個(gè)互斥加鎖。于是,雙方毫無進(jìn)展,因?yàn)樗鼈兺瑫r(shí)在苦苦等待對(duì)方解鎖互斥。此時(shí)造成死鎖。
死鎖:兩個(gè)線程互相等待,停滯不前。

防范死鎖的建議通常是始終按相同的順序?qū)蓚€(gè)互斥加鎖。若我們總是先鎖互斥A,在鎖互斥B,則永遠(yuǎn)不會(huì)發(fā)生死鎖。

(1)運(yùn)用std::lock函數(shù)和std::lock_guard類模版,進(jìn)行內(nèi)部數(shù)據(jù)的互換操作:

class some_big_object;
void swap(some_big_object& lhs, some_big_object& rhs);
class X
{
private:
	some_big_object some_detail;
	std::mutex m;
public:
	X(some_big_object const& sd):some_detail(sd){}
	friend void swap(X& lhs, X& rhs)
	{
		if(&lhs == &rhs)
			return;
		std::lock(lhs.m, rhs.m);
		//std::adopt_lock指明互斥上已被鎖住,即互斥上有鎖存在
		std::lock_guard<std::mutex> lock_a(lhs.m, std::adopt_lock);
		std::lock_guard<std::mutex> lock_a(rhs.m, std::adopt_lock);
		swap(lhs.some_detail, rhs.some_detail);
    }
}

std::adopt_lock指明互斥上已被鎖住,即互斥上有鎖存在

(2)使用std::unique_lock鎖,如下代碼:

//實(shí)例std::defer_lock將互斥保留為無鎖狀態(tài)
std::unique_lock<std::mutex> lock_a(lhs.m, std::defer_lock);
std::unique_lock<std::mutex> lock_b(lhs.m, std::defer_lock);
//到這里才對(duì)互斥加鎖
std::lock(lock_a, lock_b);

std::unique_lock占用更多的空間,也比std::lock_guard更慢,但是std::unique_lock對(duì)象可以不占用關(guān)聯(lián)的互斥,具備這份靈活性需要付出代價(jià):需要存儲(chǔ)并且更新互斥信息。
std::defer_lock將互斥保留為無鎖狀態(tài)。

(3)C++17 提供一個(gè)新的RAII類模版std::scoped_lock<>。std::scoped_lock<>和std::scoped_guard<> 完全等價(jià),只不過前者是可變參數(shù)類模版,接收各種互斥類型作為模版參數(shù)類表,還以多個(gè)互斥對(duì)象作為構(gòu)造函數(shù)的參數(shù)列表。

swap(X& lhs, X& rhs)
{
	if(&lhs == &rhs)
		return;
	std::scoped_lock guard(lhs.m, rhs.m);

	swap(lhs.some_detail, rhs.some_detail);	
}

std::scoped_lock guard(lhs.m, rhs.m)等價(jià)于 std::scoped_lock<std::mutex, std::mutex> guard(lhs.m, rhs.m);

2.5 如何使用std::unique_lock轉(zhuǎn)移互斥歸屬權(quán)?

因?yàn)?code>std::unique_lock實(shí)例不占有與之關(guān)聯(lián)的互斥,所以隨著其實(shí)例的轉(zhuǎn)移,互斥的歸屬權(quán)可以在多個(gè)std::unique_lock實(shí)例之間轉(zhuǎn)移。std::unique_lock是可移動(dòng)不可復(fù)制。

轉(zhuǎn)移有一種用途:準(zhǔn)許函數(shù)鎖定互斥,然后把互斥的歸屬權(quán)轉(zhuǎn)移給函數(shù)調(diào)用者,好讓它在同一鎖的保護(hù)下執(zhí)行其他操作。

看如下代碼,get_lock() 函數(shù)先鎖定互斥,接著對(duì)數(shù)據(jù)做前期準(zhǔn)備,再將歸屬權(quán)返回給調(diào)用者:

std::unique_lock<std::mutex> get_lock()
{
	extern std::mutex some_mutex;
	std::unique_lock<std::mutex> lk(some_mutex);
	prepare_data();
	return lk;
}
void process_data()
{
	std::unique_lock<std::mutex> lk(get_lock());
	do_something();
}

由于鎖lk是get_lock函數(shù)中聲明的std::unique_lock局部變量,因此代碼無需調(diào)用std::move()就能把它直接返回,編譯器會(huì)妥善調(diào)用移動(dòng)構(gòu)造函數(shù)。

2.6 如何使用std::unique_lock按合適的粒度加鎖?

粒度精細(xì)的鎖保護(hù)少量數(shù)據(jù),而粒度粗大的鎖保護(hù)大量數(shù)據(jù)。鎖操作有兩個(gè)要點(diǎn):

  • 選擇足夠粗大的鎖粒度,確保目標(biāo)數(shù)據(jù)受到保護(hù);
  • 限制范圍,務(wù)求只在必要的操作過程中持鎖。

std::unique_lock類具有成員函數(shù)lock()unlock()、try_lock()
可用std::unique_lock處理:假如代碼不再需要訪問共享數(shù)據(jù),那么我們就調(diào)用unlock()解鎖;若以后需要重新訪問,則調(diào)用lock()加鎖。

void get_and_process_data()
{
	std::unique_lock<std::mutex> my_lock(the_mutex);
	some_class data_to_process = get_next_data_chunk();
	my_lock.unlock();
	//假定調(diào)用process()期間,互斥無須加鎖
	result_type result = process(data_to_process);
	my_lock.lock();
	//重新鎖住互斥,以寫出結(jié)果
	write_result(data_to_process, result);
}

若只用單獨(dú)一個(gè)互斥保護(hù)整個(gè)數(shù)據(jù)結(jié)構(gòu),不但可以加劇鎖的爭(zhēng)奪,還將難以縮短縮短持鎖時(shí)間。假設(shè)某種操作需對(duì)同一個(gè)互斥全程加鎖,當(dāng)中步驟越多,則持鎖時(shí)間越久。這是一種雙重?fù)p失,恰恰加倍促使我們盡可能該用粒度精細(xì)的鎖。

比如刪除某數(shù)據(jù),得先進(jìn)行查詢?cè)賱h除,可以先獲取拷貝對(duì)象數(shù)據(jù),遍歷完再進(jìn)行刪除。減少鎖持續(xù)時(shí)間。

2.7 如果對(duì)很少更新的數(shù)據(jù)結(jié)構(gòu)該如何優(yōu)化加鎖?

采用std::mutex保護(hù)數(shù)據(jù)結(jié)構(gòu)過于嚴(yán)苛,原因是即便沒發(fā)生改動(dòng),他照樣會(huì)禁止并發(fā)訪問。C++17標(biāo)準(zhǔn)庫提供std::share_mutex,我們需要采用新類型的互斥。由于新類型的互斥具有兩種不同的使用方式,因此通常被稱為讀寫互斥:允許單獨(dú)一個(gè)“寫線程”進(jìn)行完全排它訪問,也允許多個(gè)“讀線程”共享數(shù)據(jù)或并發(fā)訪問。

共享鎖即讀鎖,對(duì)應(yīng)std::shared_lock<std::shared_mutex>
排他鎖即寫鎖,對(duì)應(yīng)std::lock_guard<std::shared_mutex>和std::unique_guard<std::shared_mutex>

運(yùn)用 std::shared_mutex 保護(hù)數(shù)據(jù)結(jié)構(gòu),代碼如下:

#include <map>
#include <string>
#include <mutex>
#include <shared_mutex>
class dns_enty;
class dns_cache
{
	std::map<std::string, dns_entry> entries;
	mutable std::shared_mutex entry_mutex;
public:
	dns_entry find_entry(std::string const& domain) const
	{
		std::shared_lock<std::shared_mutex> lk(entry_mytex);
		std::map<std::string, dns_entry>::const_iterator const it = entries.find(domain);
		return(it == entries.end()) ? dns_entry() : it->second;
	}
	void update_or_add_entry(std::string const& domain, dns_entry const& dns_details)
	{
		std::lock_guard<std::shared_mutex> lk(entry_mutex);
		entries[domain] = dns_details;
    }
	
};

2.8 如何遞歸加鎖?

使用std::mutex,再次對(duì)其重新加鎖就會(huì)出錯(cuò),將導(dǎo)致未定義行為。
使用std::recursive_mutex允許同一線程對(duì)某互斥的統(tǒng)一實(shí)例多次加鎖,我們必須先釋放全部的鎖,才可以讓另一個(gè)線程鎖住該互斥。

例如:
若我們對(duì)它調(diào)用3次lock(),就必須調(diào)用3次unlock()。只要正確的使用std::lock_guard<std::recurive_mutex> std::unique_guard<std::recurive_mutex>,它們便會(huì)處理好遞歸鎖。

3、多線程中如何在初始化過程中保護(hù)共享數(shù)據(jù)

用互斥實(shí)現(xiàn)線程安全的延遲初始化,代碼如下:

std::shared_ptr<some_resource> resource_ptr;
std::mutex resource_mutex;
void foo()
{
	//此處,全部線程都被迫循環(huán)運(yùn)行
	std::unique_lock<std::mutex> lk(resource_mutex);
	if(resource_ptr)
	{
		//僅有初始化需要保護(hù)數(shù)據(jù)
		resource_ptr.reset(new some_resource);
	}
	lk.unlock();
	resource_ptr->do_something();
}

不過數(shù)據(jù)為多線程使用,那么它們便無法并發(fā)訪問,線程只能毫無必要的運(yùn)行,因?yàn)槊總€(gè)線程都必須在互斥上輪候,等待查驗(yàn)數(shù)據(jù)是否已經(jīng)完成初始化。

為此,C++標(biāo)準(zhǔn)庫中提供了std::once_flag類和std::call_once()函數(shù)。
令所有線程共同調(diào)用std::call_once函數(shù),從而確保在該調(diào)用返回時(shí),指針初始化由其中某線程安全且唯一完成(通過適合的同步機(jī)制)。必要同步數(shù)據(jù)則有std::once_flag實(shí)例存儲(chǔ),每個(gè)std::call_flag實(shí)例對(duì)應(yīng)一次不同的初始化。相比顯示使用互斥,std::call_once()函數(shù)的額外開銷往往更低,特別是在初始已經(jīng)完成的情況下,所以如果功能符合需求就應(yīng)優(yōu)先使用。

延遲初始化代碼如下:

std::shared_ptr<some_resource> resource_ptr;
//實(shí)例存儲(chǔ)
std::once_flag resource_flag;
void init_resource()
{
	resource_ptr.reset(new some_resource);
}
void foo()
{
	//初始化函數(shù)準(zhǔn)確地被唯一一次調(diào)用
	std::call_once(resource_flag, init_resource);
	resource_ptr->do_something();
}

利用std::call_once()函數(shù)對(duì)類X的數(shù)據(jù)成員實(shí)施線程安全的延遲初始化:

class X
{
private:
	connection_info connection_details;
	connection_handle connection;
	std::once_flag connection_init_flag;
	void open_connection()
	{
		connection = connection_manager.open(connection_details);
    }
public:
	X(connection_info const& connection_details_);
		connection_details(connection_details_)
		{}
	void send_data(data_packet const& data)
	{
		std::call_once(connection_init_flag, &X::open_connection, this);
		connection.send_data(data);
	}
	data_packet receive_data()
	{
		std::call_once(connection_init_flag, &X::open_connection, this);
		return connection.receive_data();
	}
};

某些類的代碼只需用到唯一一個(gè)全局實(shí)例,這種情形可用以下方法代替std::call_once():

class my_class;
//線程安全的初始化,C++11標(biāo)準(zhǔn)保證其正確性
my_class& get_my_class_instance()
{
	static my_class inctance;
	return instance;
}

多個(gè)線程可以安全地調(diào)用get_my_class_instance(),而無需擔(dān)憂初始化的條件競(jìng)爭(zhēng)。

4、小結(jié)

世上無難事,只怕有心人。

點(diǎn)擊進(jìn)入系列文章目錄文章來源地址http://www.zghlxwxcb.cn/news/detail-477744.html

到了這里,關(guān)于C++并發(fā)線程 - 如何線程間共享數(shù)據(jù)【詳解:如何使用鎖操作】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • (線程池)多線程使用場(chǎng)景--es數(shù)據(jù)批量導(dǎo)入、數(shù)據(jù)匯總、異步調(diào)用;如何控制某個(gè)方法允許并發(fā)訪問線程的數(shù)量;對(duì)ThreadLocal的理解及實(shí)現(xiàn)原理、源碼解析、ThreadLocal的內(nèi)存泄露問題

    (線程池)多線程使用場(chǎng)景--es數(shù)據(jù)批量導(dǎo)入、數(shù)據(jù)匯總、異步調(diào)用;如何控制某個(gè)方法允許并發(fā)訪問線程的數(shù)量;對(duì)ThreadLocal的理解及實(shí)現(xiàn)原理、源碼解析、ThreadLocal的內(nèi)存泄露問題

    CountDownLatch(閉鎖/倒計(jì)時(shí)鎖) 用來進(jìn)行線程同步協(xié)作,等待所有線程完成倒計(jì)時(shí)(一個(gè)或者多個(gè)線程,等待其他多個(gè)線程完成某件事情之后才能執(zhí)行) 其中構(gòu)造參數(shù)用來初始化等待計(jì)數(shù)值 await() 用來等待計(jì)數(shù)歸零 countDown() 用來讓計(jì)數(shù) 減一 多線程使用場(chǎng)景一:( es數(shù)據(jù)批量導(dǎo)

    2024年04月25日
    瀏覽(46)
  • C# 使用屏障來使多線程并發(fā)操作保持同步

    C# 使用屏障來使多線程并發(fā)操作保持同步

    以下是微軟官方對(duì)屏障類的介紹,System.Threading.Barrier 可用來作為實(shí)現(xiàn)并發(fā)同步操作的基本單元,讓多個(gè)線程(參與者)分階段并行處理目標(biāo)算法。在達(dá)到代碼中的屏障點(diǎn)之前,每個(gè)參與者將繼續(xù)執(zhí)行,屏障表示工作階段的末尾;單個(gè)參與者到達(dá)屏障后將被阻止,直至所有參與者

    2024年01月24日
    瀏覽(24)
  • 在QT中使用多線程并發(fā)服務(wù)器(C++)

    在QT中使用多線程并發(fā)服務(wù)器(C++)

    什么是多線程并發(fā)服務(wù)器?在QT里如何使用多線程并發(fā)服務(wù)器呢? 多線程并發(fā)服務(wù)器是一種網(wǎng)絡(luò)服務(wù)器設(shè)計(jì),它能夠同時(shí)處理多個(gè)客戶端的請(qǐng)求。在多線程服務(wù)器中,主線程負(fù)責(zé)監(jiān)聽和接受來自客戶端的連接請(qǐng)求,每當(dāng)有一個(gè)新的連接請(qǐng)求到來時(shí),服務(wù)器就會(huì)創(chuàng)建一個(gè)新的線

    2024年04月11日
    瀏覽(21)
  • 解決在使用 Elasticsearch(ES)多線程批量操作時(shí)導(dǎo)致并發(fā)一致性的問題??!

    解決在使用 Elasticsearch(ES)多線程批量操作時(shí)導(dǎo)致并發(fā)一致性的問題??!

    先說一下什么是數(shù)據(jù)庫數(shù)據(jù)庫中 并發(fā)一致性 問題! 1、在并發(fā)環(huán)境下,事務(wù)的隔離性很難保證,因此會(huì)出現(xiàn)很多并發(fā)一致性問題。 數(shù)據(jù)丟失 T1 和 T2 兩個(gè)事務(wù)都對(duì)一個(gè)數(shù)據(jù)進(jìn)行修改,T1 先修改,T2 隨后修改,T2 的修改覆蓋了 T1 的修改。 讀臟數(shù)據(jù) T1 修改一個(gè)數(shù)據(jù),T2 隨后讀取

    2024年02月04日
    瀏覽(26)
  • C++并發(fā)操作解密:輕松搞定數(shù)據(jù)同步

    C++并發(fā)操作解密:輕松搞定數(shù)據(jù)同步

    ? 概述: 在C++中,通過互斥鎖解決并發(fā)數(shù)據(jù)同步問題。定義共享數(shù)據(jù)和互斥鎖,編寫線程函數(shù),使用互斥鎖確保操作的原子性。主函數(shù)中創(chuàng)建并啟動(dòng)線程,保障線程安全。實(shí)例源代碼演示了簡(jiǎn)單而有效的同步機(jī)制。 在C++中解決并發(fā)操作時(shí)的數(shù)據(jù)同步問題通常需要使用互斥鎖

    2024年02月04日
    瀏覽(22)
  • 【javaEE面試題(四)線程不安全的原因】【1. 修改共享數(shù)據(jù) 2. 操作不是原子性 3. 內(nèi)存可見性 4. 代碼順序性】

    【javaEE面試題(四)線程不安全的原因】【1. 修改共享數(shù)據(jù) 2. 操作不是原子性 3. 內(nèi)存可見性 4. 代碼順序性】

    大家觀察下是否適用多線程的現(xiàn)象是否一致?同時(shí)嘗試思考下為什么會(huì)有這樣的現(xiàn)象發(fā)生呢? 原因是 1.load 2. add 3. save 注意:可能會(huì)導(dǎo)致 小于5w 想給出一個(gè)線程安全的確切定義是復(fù)雜的,但我們可以這樣認(rèn)為: 如果多線程環(huán)境下代碼運(yùn)行的結(jié)果是符合我們預(yù)期的,即在單線

    2024年02月13日
    瀏覽(44)
  • 【多線程及高并發(fā) 六】并發(fā)集合及線程池詳解

    【多線程及高并發(fā) 六】并發(fā)集合及線程池詳解

    ??作者簡(jiǎn)介:大家好,我是若明天不見,BAT的Java高級(jí)開發(fā)工程師,CSDN博客專家,后端領(lǐng)域優(yōu)質(zhì)創(chuàng)作者 ??系列專欄:多線程及高并發(fā)系列 ??其他專欄:微服務(wù)框架系列、MySQL系列、Redis系列、Leetcode算法系列、GraphQL系列 ??如果感覺博主的文章還不錯(cuò)的話,請(qǐng)??點(diǎn)贊收藏關(guān)

    2024年02月01日
    瀏覽(24)
  • 【C++】多線程(thread)使用詳解

    【C++】多線程(thread)使用詳解

    多線程(multithreading),是指在軟件或者硬件上實(shí)現(xiàn)多個(gè)線程并發(fā)執(zhí)行的技術(shù)。具有多核CPU的支持的計(jì)算機(jī)能夠真正在同一時(shí)間執(zhí)行多個(gè)程序片段,進(jìn)而提升程序的處理性能。在一個(gè)程序中,這些獨(dú)立運(yùn)行的程序片段被稱為“ 線程 ”(Thread),利用其編程的概念就叫作“多線

    2024年02月14日
    瀏覽(21)
  • 并發(fā),并行,線程與UI操作

    并行和并發(fā)是計(jì)算機(jī)領(lǐng)域中兩個(gè)相關(guān)但不同的概念。 并行(Parallel)指的是同時(shí)執(zhí)行多個(gè)任務(wù)或操作 ,它依賴于具有多個(gè)處理單元的系統(tǒng)。在并行計(jì)算中,任務(wù)被分成多個(gè)子任務(wù),并且這些子任務(wù)可以同時(shí)在不同的處理單元上執(zhí)行,從而加速整體的計(jì)算速度。并行計(jì)算能夠充

    2024年01月21日
    瀏覽(27)
  • Python之并發(fā)多線程操作

    Python之并發(fā)多線程操作

    multiprocess模塊的完全模仿了threading模塊的接口,二者在使用層面,有很大的相似性 方式一 方式二 1 誰的開啟速度快 2 瞅一瞅pid 3 同一進(jìn)程內(nèi)的線程共享該進(jìn)程的數(shù)據(jù)? 練習(xí)一: 多線程并發(fā)的socket服務(wù)端 客戶端 練習(xí)二:三個(gè)任務(wù),一個(gè)接收用戶輸入,一個(gè)將用戶輸入的內(nèi)容

    2024年02月07日
    瀏覽(17)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包