C++多线程4——锁竞争
一、为什么要锁
锁是为了防止多线访问共同内存时的冲突问题,先看实例:两个线程分别对全局变量累加:
//gcc lock_test.c -lpthread
#include
#include
#include
int num = 0; //设置为全局变量,在全局区域共享
void* myfun(void* arg);
pthread_mutex_t mtx;
int main()
{
//1.产生两个线程,分别对全局变量累加
pthread_t id[2];
pthread_mutex_init(&mtx,NULL);
for (int i = 0; i < 2; i++) {
pthread_create(&(id[i]), NULL, myfun, NULL);
}
pthread_join(id[0],NULL);
pthread_join(id[1],NULL);
printf("%d\n",num);
return 0;
}
void* myfun(void* arg)
{
int i;
for(i=0;i<100000000;i++){
// pthread_mutex_lock(&mtx);
num++;
// pthread_mutex_unlock(&mtx);
}
return NULL;
}
如果没有加锁,num的结果每次都不一样:
如果加锁(myfun的注释部分),最后的结果才正确,但时间会更长。
二、锁竞争的妙用
回顾C++多线程前面三篇的例子,我们都是给固定的线程分配任务,然后每个线程完成任务后就销毁,但是如果每个任务的计算量不一样,那么就会造成负载不均衡,先完成任务的线程不能“帮助”后完成任务的线程。
现实生活中,一群人干活,干的快的可以帮助干的慢的,那么在多线程的框架下如何实现呢?
这时候,“锁”的妙用来了!假设我们的任务时计算一万个矩阵的逆,各矩阵间不相关,但大小不一,比较随机。如何让这些线程“互帮互助”呢?
一个很巧妙的方式是,我们仍然设置一个全局累加变量,但需要稍微修改改myfun:
void* myfun(void* arg)
{
int i;
while(1){
pthread_mutex_lock(&mtx);
i = num;
if(i>=10000){
pthread_mutex_unlock(&mtx);
break;
}
num++;
pthread_mutex_unlock(&mtx);
task_invmatrix[i];//执行第i个任务
}
各个线程先争夺全局变量num,修改num之后,执行第i(=num)个任务,由于任务的时间远大于加锁、修改num、解锁的时间,这样便实现了各线程的互帮互助!
更多实例可以参看我的gitee:ptread_lock