关于线程的访问数据

对于任何一个进程来讲,即便我们没有主动去创建线程,进程也是默认有一个主线程的。线程是负责执行二进制指令的,它会根据项目执行计划书,一行一行执行下去。进程要比线程管的宽多了,除了执行指令之外,内存、文件系统等等都要它来管。

进程相当于一个项目,而线程就是为了完成项目需求,而建立的一个个开发任务。默认情况下,你可以建一个大的任务,就是完成某某功能,然后交给一个人让它从头做到尾,这就是主线程。但是有时候,你发现任务是可以拆解的,如果相关性没有非常大前后关联关系,就可以并行执行。

使用进程实现并行执行的问题也有两个。第一,创建进程占用资源太多;第二,进程之间的通信需要数据在不同的内存空间传来传去,无法共享。

把线程访问的数据细分成三类:

第一类是线程栈上的本地数据,比如函数执行过程中的局部变量。函数的调用会使用栈的模型,这在线程里面是一样的。只不过每个线程都有自己的栈空间。

主线程在内存中有一个栈空间,其他线程栈也拥有独立的栈空间。为了避免线程之间的栈空间踩踏,线程栈之间还会有小块区域,用来隔离保护各自的栈空间。一旦另一个线程踏入到这个隔离区,就会引发段错误。

第二类数据就是在整个进程里共享的全局数据。例如全局变量,虽然在不同进程中是隔离的,但是在一个进程中是共享的。如果同一个全局变量,两个线程一起修改,那肯定会有问题,有可能把数据改的面目全非。

这就是第三类数据,线程私有数据(Thread Specific Data),可以通过以下函数创建:

int pthread_key_create(pthread_key_t *key, void (*destructor)(void*))

可以看到,创建一个 key,伴随着一个析构函数。key 一旦被创建,所有线程都可以访问它,但各线程可根据自己的需要往 key 中填入不同的值,这就相当于提供了一个同名而不同值的全局变量。

此文章为3月Day29 学习笔记,内容来源于极客时间《趣谈 Linux 操作系统》,推荐该课程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++多线程数据访问可以通过队列和共享数据来实现。队列是一种封装好的数据结构,可以用来在多个线程之间进行数据交互,使用队列可以较少出错的可能性。共享数据则是指多个线程共同访问数据,但是它容易产生数据争用的情况,即多个线程同时抢占某个资源,可能导致数据错乱或不一致的问题。 在C++,可以通过使用原子类型(atomic)来实现多线程间的数据访问。原子类型是一种特殊的数据类型,可以保证对其进行读写操作是原子的,即不会被其他线程断。使用原子类型可以避免数据竞争的问题。 另外,C++还提供了互斥量(mutex)和条件变量(condition_variable)来实现线程间的同步。互斥量用于保护共享资源,只有持有互斥量的线程才能访问共享资源,其他线程需要等待互斥量的释放才能访问。条件变量用于线程间的条件同步,可以实现线程的等待和唤醒操作。 下面是三种实现多线程数据访问的示例代码: 示例1: 使用原子类型 ``` #include <iostream> #include <thread> #include <atomic> using namespace std; #define COUNT 10000 void inc(atomic<int> *p){ for(int i = 0; i < COUNT; i++){ (*p)++; } } int main() { atomic<int> a{0}; thread ta(inc, &a); thread tb(inc, &a); ta.join(); tb.join(); cout << "a = " << a << endl; return 0; } ``` 示例2: 使用互斥量 ``` #include <iostream> #include <thread> #include <mutex> using namespace std; #define COUNT 10000 static mutex g_mutex; void inc(int *p){ for(int i = 0; i < COUNT; i++){ g_mutex.lock(); (*p)++; g_mutex.unlock(); } } int main() { int a{0}; thread ta(inc, &a); thread tb(inc, &a); ta.join(); tb.join(); cout << "a = " << a << endl; return 0; } ``` 示例3: 使用条件变量 ``` #include <iostream> #include <thread> #include <mutex> #include <condition_variable> using namespace std; #define COUNT 10000 static mutex g_mutex; static condition_variable g_cv; static bool g_ready = false; void inc(int *p){ for(int i = 0; i < COUNT; i++){ unique_lock<mutex> lock(g_mutex); g_cv.wait(lock, []{ return g_ready; }); (*p)++; g_ready = false; g_cv.notify_one(); } } int main() { int a{0}; thread ta(inc, &a); thread tb(inc, &a); ta.join(); tb.join(); cout << "a = " << a << endl; return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值