国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

網(wǎng)站制作報價明細表bt磁力狗

網(wǎng)站制作報價明細表,bt磁力狗,河北seo優(yōu)化,網(wǎng)絡(luò)推廣公司口碑目錄 1.線程的互斥 1.1.進程線程間的互斥相關(guān)背景概念 1.2.互斥量mutex的基本概念 所以多線程之間為什么要有互斥? 為什么搶票會搶到負數(shù),無法獲得正確結(jié)果? 為什么--操作不是原子性的呢? 解決方式: 2.三種加鎖…

目錄

1.線程的互斥

1.1.進程線程間的互斥相關(guān)背景概念

1.2.互斥量mutex的基本概念

所以多線程之間為什么要有互斥?

為什么搶票會搶到負數(shù),無法獲得正確結(jié)果?

為什么--操作不是原子性的呢?

解決方式:

2.三種加鎖的方式

2.1全局變量(靜態(tài)分布)的鎖

2.2局部變量(動態(tài)分布)的鎖

2.3.銷毀鎖(互斥量)的方式:

2.4.互斥量加鎖和解鎖

2.5?RAII風(fēng)格的鎖

代碼:

3.互斥的底層實現(xiàn)?

1.線程的互斥

1.1.進程線程間的互斥相關(guān)背景概念

  • 臨界資源:多線程執(zhí)行流共享的資源就叫做臨界資源
  • 臨界區(qū):每個線程內(nèi)部,訪問臨界資源的代碼,就叫做臨界區(qū)
  • 互斥:任何時刻,互斥保證有且只有一個執(zhí)行流進入臨界區(qū),訪問臨界資源,通常對臨界資源起保護作用
  • 原子性(后面討論如何實現(xiàn)):不會被任何調(diào)度機制打斷的操作,該操作只有兩態(tài),要么完成,要么未完成

1.2.互斥量mutex的基本概念

  • 大部分情況,線程使用的數(shù)據(jù)都是局部變量,變量的地址空間在線程??臻g內(nèi),這種情況,變量歸屬單個線程,其他線程無法獲得這種變量。
  • 但有時候,很多變量都需要在線程間共享,這樣的變量稱為共享變量,可以通過數(shù)據(jù)的共享,完成線程之間的交互。
  • 多個線程并發(fā)的操作共享變量,會帶來一些問題

所以多線程之間為什么要有互斥?

上面概念有些抽象,我們來看一個實際的例子方便我們理解——搶票系統(tǒng):

代碼:

// 操作共享變量會有問題的售票系統(tǒng)代碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
int ticket = 100;
void *route(void *arg)
{
char *id = (char*)arg;
while ( 1 ) {
if ( ticket > 0 ) {
usleep(1000);
printf("%s sells ticket:%d\n", id, ticket);
ticket--;
} else {
break;
}
}
}
int main( void )
{
pthread_t t1, t2, t3, t4;
pthread_create(&t1, NULL, route, "thread 1");
pthread_create(&t2, NULL, route, "thread 2");
pthread_create(&t3, NULL, route, "thread 3");
pthread_create(&t4, NULL, route, "thread 4");
pthread_join(t1, NULL);
pthread_join(t2, NULL);pthread_join(t3, NULL);
pthread_join(t4, NULL);
}

執(zhí)行結(jié)果:

這是沒有加鎖(互斥)的代碼執(zhí)行的結(jié)果,發(fā)現(xiàn)我們搶票搶著搶著竟然搶到了負數(shù)!這是萬萬不行的。

為什么搶票會搶到負數(shù),無法獲得正確結(jié)果?

共享資源被訪問的時候,沒有被保護,并且本身操作不是原子的!

  1. if 語句判斷條件為真以后,代碼可以并發(fā)的切換到其他線程
  2. usleep 這個模擬漫長業(yè)務(wù)的過程,在這個漫長的業(yè)務(wù)過程中,可能有很多個線程會進入該代碼段
  3. --ticket 操作本身就不是一個原子操作

前兩者我們好理解,

為什么--操作不是原子性的呢?

ticket需要先從內(nèi)存中讀取數(shù)據(jù)放在CPU上,然后CPU進行加法或者減法操作,最后再將數(shù)據(jù)放在內(nèi)存當(dāng)中。因此就不是原子性的。

-- 操作并不是原子操作,而是對應(yīng)三條匯編指令:

  • load :將共享變量ticket從內(nèi)存加載到寄存器中
  • update : 更新寄存器里面的值,執(zhí)行-1操作
  • store :將新值,從寄存器寫回共享變量ticket的內(nèi)存地址

解決方式:

要解決以上問題,需要做到三點:

  • 代碼必須要有互斥行為:當(dāng)代碼進入臨界區(qū)執(zhí)行時,不允許其他線程進入該臨界區(qū)。
  • 如果多個線程同時要求執(zhí)行臨界區(qū)的代碼,并且臨界區(qū)沒有線程在執(zhí)行,那么只能允許一個線程進入該臨界區(qū)。
  • 如果線程不在臨界區(qū)中執(zhí)行,那么該線程不能阻止其他線程進入臨界區(qū)。

要做到這三點,本質(zhì)上就是需要一把鎖。Linux上提供的這把鎖叫互斥量。

2.三種加鎖的方式

2.1全局變量(靜態(tài)分布)的鎖

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER

注意這種鎖是定義在全局代碼段的,這種鎖也不需要銷毀

2.2局部變量(動態(tài)分布)的鎖

int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict
attr);
參數(shù):
mutex:要初始化的互斥量
attr:NULL

這種鎖需要我們在局部代碼段進行定義和初始化,并且也需要我們自己去手動銷毀。

2.3.銷毀鎖(互斥量)的方式:

int pthread_mutex_destroy(pthread_mutex_t *mutex)

注意以上這兩種鎖的使用都是需要在指定加鎖的區(qū)域進行加鎖和解鎖。

2.4.互斥量加鎖和解鎖

int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
返回值:成功返回0,失敗返回錯誤號

2.5?RAII風(fēng)格的鎖

C++注重RAII的編程思想,所以我們可以將鎖自己封裝成為一個RAII風(fēng)格的鎖

我們可以將鎖進行封裝,定義一個LockGuard的類,里面只有一個鎖的成員變量,構(gòu)造函數(shù)是加鎖,析構(gòu)函數(shù)是解鎖,所以我們可以創(chuàng)建一個局部的對象,讓編譯器自己去調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù),這樣就不需要我們進行加鎖和解鎖

代碼:

#ifndef __LOCK_GUARD_HPP__
#define __LOCK_GUARD_HPP__#include <iostream>
#include <pthread.h>class LockGuard
{
public:LockGuard(pthread_mutex_t *mutex):_mutex(mutex){pthread_mutex_lock(_mutex); // 構(gòu)造加鎖}~LockGuard(){pthread_mutex_unlock(_mutex);//析構(gòu)解鎖}
private:pthread_mutex_t *_mutex;
};#endif

在我們學(xué)習(xí)了如何加鎖之后,我們就可以將搶票系統(tǒng)進行進一步的優(yōu)化:

void route(ThreadData *td)
{while (true){{ // 擔(dān)心就用這個LockGuard guard(&td->_mutex); // 臨時對象, RAII風(fēng)格的加鎖和解鎖//std::lock_guard<std::mutex> lock(td->_mutex);//pthread_mutex_lock(&td->_mutex);if (td->_tickets > 0) // 1{usleep(1000);printf("%s running, get tickets: %d\n", td->_name.c_str(), td->_tickets); // 2td->_tickets--;                                                           // 3//pthread_mutex_unlock(&td->_mutex);td->_total++;}else{//pthread_mutex_unlock(&td->_mutex);//td->_mutex.unlock();break;}}}
}

執(zhí)行結(jié)果:

可以看出,加鎖之后就完美解決了票數(shù)會搶到負數(shù)的問題!

3.互斥的底層實現(xiàn)?

  • 經(jīng)過上面的例子,大家已經(jīng)意識到單純的 i++ 或者 ++i 都不是原子的,有可能會有數(shù)據(jù)一致性問題
  • 為了實現(xiàn)互斥鎖操作,大多數(shù)體系結(jié)構(gòu)都提供了swap或exchange指令,該指令的作用是把寄存器和內(nèi)存單元的數(shù)據(jù)相交換,由于只有一條指令,保證了原子性,即使是多處理器平臺,訪問內(nèi)存的 總線周期也有先后,一個處理器上的交換指令執(zhí)行時另一個處理器的交換指令只能等待總線周期。?

所有線程在爭鎖的時候,只有一個鎖,交換的過程,只有一條是匯編——所以該過程是原子的

CPU寄存器硬件只有一套,但是CPU寄存器內(nèi)部的數(shù)據(jù),數(shù)據(jù)線程的硬件上下文是有多套的。

數(shù)據(jù)在內(nèi)存中,所有的線程都能訪問,屬于共享的。但是如果轉(zhuǎn)移到CPU內(nèi)部寄存器中,就屬于一個線程私有的了!!!

http://aloenet.com.cn/news/36071.html

相關(guān)文章:

  • 超市網(wǎng)站模版網(wǎng)絡(luò)推廣培訓(xùn)班
  • 鄭州網(wǎng)站推廣排名公司浙江關(guān)鍵詞優(yōu)化
  • 萬網(wǎng)網(wǎng)站建設(shè)購買過程汽車推廣軟文
  • 怎么自己的電腦做網(wǎng)站服務(wù)器百度網(wǎng)站是什么
  • 阿里巴巴怎么做公司網(wǎng)站我為什么不建議年輕人做銷售
  • 網(wǎng)站建設(shè) 資訊動態(tài)電商軟文范例100字
  • 網(wǎng)站文化建設(shè)軟文新聞發(fā)布網(wǎng)站
  • 徐州企業(yè)網(wǎng)站設(shè)計免費的網(wǎng)站推廣在線推廣
  • 歐美設(shè)計網(wǎng)站推薦百度推廣賬號怎么申請
  • 如何寫好網(wǎng)站開發(fā)技術(shù)文檔頭條新聞今日頭條官方版本
  • 網(wǎng)站建設(shè)本科畢業(yè)設(shè)計論文鄭州網(wǎng)站推廣排名公司
  • 發(fā)果怎么做視頻網(wǎng)站四川省最新疫情情況
  • 一個網(wǎng)站怎么做鏡像站熱點事件
  • wordpress播放器源碼徐州seo外包
  • 動態(tài)網(wǎng)站建設(shè)簡介谷歌排名網(wǎng)站優(yōu)化
  • 廣西專業(yè)做網(wǎng)站的公司軟件排名工具
  • 網(wǎng)站建設(shè)技術(shù)服務(wù)清單網(wǎng)絡(luò)營銷有哪些
  • 企業(yè)介紹微網(wǎng)站怎么做短視頻營銷推廣策略
  • c 網(wǎng)站開發(fā)框架百度小說風(fēng)云榜今天
  • 企業(yè)網(wǎng)站建設(shè)合同書模板可以引流推廣的app
  • 云瓣科技做網(wǎng)站本地網(wǎng)絡(luò)seo公司
  • 網(wǎng)站后臺登陸代碼百度關(guān)鍵詞seo排名
  • 用js做跳轉(zhuǎn)到其他網(wǎng)站優(yōu)化公司怎么優(yōu)化網(wǎng)站的
  • 大場網(wǎng)站建設(shè)seo最好的工具
  • 國外做的比較好看的網(wǎng)站2022年度最火關(guān)鍵詞
  • 西安網(wǎng)站建設(shè)開發(fā)查派谷歌seo排名公司
  • 依波手表價格 官方網(wǎng)站360搜索優(yōu)化
  • 網(wǎng)站建設(shè)客戶告知書長春網(wǎng)站優(yōu)化團隊
  • 鄭州區(qū)塊鏈數(shù)字錢包網(wǎng)站開發(fā)多少錢廣州網(wǎng)頁制作
  • 網(wǎng)站管理建設(shè)的總結(jié)抖音代運營