多线程与线程安全

Multithread

Posted by 朱晓旭 on January 7, 2021

进程(Process)

狭义的进程是正在运行的程序的实例;广义的进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,是操作系统动态执行的基本单元。进程间数据不共享(因此才会有进程间通讯这个课题,进程间通讯的方法有:匿名管道,有名管道,消息队列,信号量,信号,共享内存,套接字等等)。

线程(Thread)

线程是程序执行流的最小单位;一个标准的线程由线程ID、当前指令指针(PC)、寄存器集合和堆栈组成。通常情况下,一个进程由一个到多个线程组成,各个线程之间共享程序的内存空间及一些进程级的资源。同一个进程中线程间的数据是共享的,这才会带来当多个线程同时操作同一个内存时,带来的线程安全问题。

理解: c++中的一条置零在被操作系统编译后生成的机器码往往是多条(机器码是不可打断的最小执行指令),当不同线程的指令,同时改变同一个寄存器数值时,带来的结果不是不可预见的,这当然不是我们希望的。 原则上,凡是线程间共享的可变量是都是不安全的。比如全局变量和静态变量(静态变量可能会被多次初始化)。

实现线程安全的方法

线程锁(Lock)

#include <iostream>    
#include <thread>    
#include <mutex>    

/*  线程间数据共享,当多个线程同时操作同一个数据时,需要加入线程锁,保证同时操作一个数据的安全性  */

std::mutex mt; 
int data = 1;

void addmethod(int a)
{
  mt.lock();
  data += a;
  std::cout << "add data=" << data << std::endl;
  mt.unlock();
}

void multimethod(int a)
{
  mt.lock();
  data *= a;
  std::cout << "multipy add=" << data << std::endl;
  mt.unlock();
}

int main()
{
  std::thread t1(addmethod,2);
  std::thread t2(multimethod,10);

  t1.detach(); //detach()是非阻塞,独立于主线程并发执行。(相反的join则是阻塞主线程)
  t2.detach();

  getchar();
  return 0;
}