1. 程式人生 > >C/C++函式的本質以及多執行緒函式的呼叫過程

C/C++函式的本質以及多執行緒函式的呼叫過程

C/C++中,函式的本質是一段可執行程式碼,程式碼包括了局部變數、全域性變數的地址等等。到組合語言的級別,變數函式等都可以視為彙編的程式碼片段。函式的本質就是一個可執行程式碼片段的集合

執行緒的詳細介紹:http://www.cnblogs.com/tracylee/archive/2012/10/29/2744228.html
一個執行緒有自己的空間,有自己的區域性變數。當一個執行緒執行一個函式的時候,會複製函式的程式碼段到自己的執行緒空間,之後執行該程式碼段。對於區域性變數,每個執行緒會儲存一個區域性變數的副本,因為區域性變數是儲存在棧記憶體,所以一個執行緒更改區域性變數不會影響其他執行緒的區域性變數。全域性變數是儲存在堆記憶體上的,因此可以理解為執行緒是直接操作堆記憶體上的全域性變數,因此如果一個執行緒改了全域性變數,那麼其他執行緒對應的全域性變數肯定會更改,因為堆記憶體只有一個。

在多執行緒程式設計的過程中,所謂的新增互斥量、鎖和條件變數等,本質上是為了保護堆記憶體上的東西,或者說是全域性變數。所謂的競爭條件也是指的全域性的,函式內部的區域性的東西,不會引起競爭!!!!!

可以這麼認為,對於C++11中的std:thread來說,函式是其執行的基本單位,這裡說的函式包括普通函式、函式物件、std::funtion、仿函式、lambda表示式等。執行的時候,執行緒會複製函式的程式碼片段到自己的執行緒空間中去執行。執行緒空間的本身是封閉的,也就是說一個同級別的執行緒不能更改另一個執行緒的程式碼片段。。我們說的執行緒之間的通訊,本質上說的是通過全域性變數的狀態,使得不同執行緒之間可以相互通訊!!!

對於類的成員函式來說,執行緒複製函式的時候,類的成員變數相對於執行緒來說也是全域性!!!!

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>

static int N = 0;

void fun(int n) {
  int t = 0;
  for (int i = 0; i < n; ++i) {
    ++t;
    ++N;
  }
  std::this_thread::
sleep_for(std::chrono::milliseconds(100)); std::cout << "local: " << t << std::endl; std::cout << "global: " << N << std::endl; } class C { public: void fun(int n) { int t = 0; for (int i = 0; i < n; ++i) { ++t; ++_N; } std::this_thread::sleep_for(std::chrono::milliseconds(100)); std::cout << "local: " << t << std::endl; std::cout << "global: " << _N << std::endl; } int _N; // 這裡的_N相對於fun函式是全域性的!!!!!!! }; int main() { // 函式的例子 std::cout << "function example:\n"; std::thread t1(fun, 100000); std::thread t2(fun, 100000); t1.join(); t2.join(); std::this_thread::sleep_for(std::chrono::milliseconds(500)); // 類的例子 std::cout << "\nclass example:\n"; C c; c._N = 0; std::thread t3(&C::fun, &c, 100000); std::thread t4(&C::fun, &c, 100000); t3.join(); t4.join(); return 0; }

一種可能的執行結果:

function example:
local: 100000
global: 109248
local: 100000
global: 109248

class example:
local: 100000
global: 115581
local: 100000
global: 115581