iis服务器助手广告广告
返回顶部
首页 > 资讯 > 操作系统 >Linux线程互斥锁的概念
  • 157
分享到

Linux线程互斥锁的概念

2023-06-15 21:06:18 157人浏览 泡泡鱼
摘要

本篇内容介绍了“linux线程互斥锁的概念”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在编程中,引入了对象互斥锁的概念,来保证共享数据操作

本篇内容介绍了“linux线程互斥的概念”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为" 互斥锁"  的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。

Linux实现的互斥锁机制包括POSIX互斥锁和内核互斥锁,本文主要讲POSIX互斥锁,即线程间互斥锁。

“ 信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在sem_wait的时候,就阻塞在  那里)。而互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这  个资源。比如对全局变量的访问,有时要加锁,操作完了,在解锁。有的时候锁和信号量会同时使用的”

也就是说,信号量不一定是锁定某一个资源,而是  流程上的概念,比如:有A,B两个线程,B线程要等A线程完成某一任务以后再进行自己下面的步骤,这个任务并不一定是锁定某一资源,还可以是进行一些计算  或者数据处理之类。而线程互斥量则是“锁住某一资源”的概念,在锁定期间内,其他线程无法对被保护的数据进行操作。在有些情况下两者可以互换。

两者之间的区别:

作用域

信号量 : 进程间或线程间(linux仅线程间)

互斥锁 : 线程间

上锁时

信号量 :  只要信号量的value大于0,其他线程就可以sem_wait成功,成功后信号量的value减一。若value值不大于0,则sem_wait阻塞,直到sem_post释放后value值加一。一句话,信号量的value>=0  。

互斥锁 : 只要被锁住,其他任何线程都不可以访问被保护的资源。如果没有锁,获得资源成功,否则进行阻塞等待资源可用。一句话,线程互斥锁的vlaue可以为负数  。

多线程

线程是计算机中独立运行的最小单位,运行时占用很少的系统资源。与多进程相比,多进程具有多进程不具备的一些优点,其最重要的是:对于多线程来说,其能够比多进程更加节省资源。

线程创建

在Linux中,新建的线程并不是在原先的进程中,而是系统通过一个系统调用clone()。该系统copy了一个和原先进程完全一样的进程,并在这个进程中执行线程函数。

在Linux中,通过函数pthread_create()函数实现线程的创建:

pthread_create()

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*st

其中:

  • thread表示的是一个pthread_t类型的指针;

  • attr用于指定线程的一些属性;

  • start_routine表示的是一个函数指针,该函数是线程调用函数;

  • arg表示的是传递给线程调用函数的参数。

当线程创建成功时,函数pthread_create()返回0,若返回值不为0则表示创建线程失败。对于线程的属性,则在结构体pthread_attr_t中定义。

线程创建的过程如下所示:

#include <stdio.h> #include <pthread.h> #include <unistd.h> #include <malloc.h>  void* thread(void *id){    pthread_t newthid;     newthid = pthread_self();    printf("this is a new thread, thread ID is %u\n", newthid);    return NULL; }  int main(){  int num_thread = 5;  pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread);   printf("main thread, ID is %u\n", pthread_self());  for (int i = 0; i < num_thread; i++){        if (pthread_create(&pt[i], NULL, thread, NULL) != 0){           printf("thread create failed!\n");           return 1;        }  }  sleep(2);  free(pt);  return 0; }

在上述代码中,使用到了pthread_self()函数,该函数的作用是获取本线程的线程ID。在主函数中的sleep()用于将主进程处于等待状态,以让线程执行完成。最终的执行效果如下所示:

Linux线程互斥锁的概念

那么,如何利用arg向子线程传递参数呢?其具体的实现如下所示:

#include <stdio.h> #include <pthread.h> #include <unistd.h> #include <malloc.h>  void* thread(void *id){   pthread_t newthid;    newthid = pthread_self();   int num = *(int *)id;   printf("this is a new thread, thread ID is %u,id:%d\n", newthid, num);   return NULL; }  int main(){   //pthread_t thid;   int num_thread = 5;   pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread);   int * id = (int *)malloc(sizeof(int) * num_thread);    printf("main thread, ID is %u\n", pthread_self());   for (int i = 0; i < num_thread; i++){      id[i] = i;      if (pthread_create(&pt[i], NULL, thread, &id[i]) != 0){         printf("thread create failed!\n");         return 1;      }   }   sleep(2);   free(pt);   free(id);   return 0; }

其最终的执行效果如下图所示:

Linux线程互斥锁的概念

如果在主进程提前结束,会出现什么情况呢?如下述的代码:

#include <stdio.h> #include <pthread.h> #include <unistd.h> #include <malloc.h>  void* thread(void *id){   pthread_t newthid;    newthid = pthread_self();   int num = *(int *)id;   printf("this is a new thread, thread ID is %u,id:%d\n", newthid, num);   sleep(2);   printf("thread %u is done!\n", newthid);   return NULL; }  int main(){   //pthread_t thid;   int num_thread = 5;   pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread);   int * id = (int *)malloc(sizeof(int) * num_thread);    printf("main thread, ID is %u\n", pthread_self());   for (int i = 0; i < num_thread; i++){      id[i] = i;      if (pthread_create(&pt[i], NULL, thread, &id[i]) != 0){         printf("thread create failed!\n");         return 1;      }    }    //sleep(2);    free(pt);    free(id);    return 0; }

此时,主进程提前结束,进程会将资源回收,此时,线程都将退出执行,运行结果如下所示:

Linux线程互斥锁的概念

线程挂起

在上述的实现过程中,为了使得主线程能够等待每一个子线程执行完成后再退出,使用了free()函数,在Linux的多线程中,也可以使用pthread_join()函数用于等待其他线程,函数的具体形式为:

int pthread_join(pthread_t thread, void **retval);

函数pthread_join()用来等待一个线程的结束,其调用这将被挂起。

一个线程仅允许一个线程使用pthread_join()等待它的终止。

如需要在主线程中等待每一个子线程的结束,如下述代码所示:

#include <stdio.h> #include <pthread.h> #include <unistd.h> #include <malloc.h>  void* thread(void *id){   pthread_t newthid;    newthid = pthread_self();   int num = *(int *)id;   printf("this is a new thread, thread ID is %u,id:%d\n", newthid, num);    printf("thread %u is done\n", newthid);   return NULL; }  int main(){    int num_thread = 5;    pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread);    int * id = (int *)malloc(sizeof(int) * num_thread);     printf("main thread, ID is %u\n", pthread_self());    for (int i = 0; i < num_thread; i++){       id[i] = i;       if (pthread_create(&pt[i], NULL, thread, &id[i]) != 0){          printf("thread create failed!\n");          return 1;        }    }    for (int i = 0; i < num_thread; i++){       pthread_join(pt[i], NULL);    }    free(pt);    free(id);    return 0; }

最终的执行效果如下所示:

Linux线程互斥锁的概念

注:在编译的时候需要链接libpthread.a:

g++ xx.c -lpthread -o xx

互斥锁mutex

多线程的问题引入

多线程的最大的特点是资源的共享,但是,当多个线程同时去操作(同时去改变)一个临界资源时,会破坏临界资源。如利用多线程同时写一个文件:

#include <stdio.h> #include <pthread.h> #include <malloc.h>  const char filename[] = "hello";  void* thread(void *id){   int num = *(int *)id;    // 写文件的操作   FILE *fp = fopen(filename, "a+");   int start = *((int *)id);   int end = start + 1;   setbuf(fp, NULL);// 设置缓冲区的大小   fprintf(stdout, "%d\n", start);   for (int i = (start * 10); i < (end * 10); i ++){       fprintf(fp, "%d\t", i);   }   fprintf(fp, "\n");   fclose(fp);   return NULL; }  int main(){    int num_thread = 5;    pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread);    int * id = (int *)malloc(sizeof(int) * num_thread);     for (int i = 0; i < num_thread; i++){       id[i] = i;       if (pthread_create(&pt[i], NULL, thread, &id[i]) != 0){          printf("thread create failed!\n");          return 1;          }    }    for (int i = 0; i < num_thread; i++){       pthread_join(pt[i], NULL);    }    // 释放资源    free(pt);    free(id);    return 0; }

执行以上的代码,我们会发现,得到的结果是混乱的,出现上述的最主要的原因是,我们在编写多线程代码的过程中,每一个线程都尝试去写同一个文件,这样便出现了上述的问题,这便是共享资源的同步问题,在Linux编程中,线程同步的处理方法包括:信号量,互斥锁和条件变量。

互斥锁

互斥锁是通过锁的机制来实现线程间的同步问题。互斥锁的基本流程为:

  • 初始化一个互斥锁:pthread_mutex_init()函数

  • 加锁:pthread_mutex_lock()函数或者pthread_mutex_trylock()函数

  • 对共享资源的操作

  • 解锁:pthread_mutex_unlock()函数

  • 注销互斥锁:pthread_mutex_destory()函数

其中,在加锁过程中,pthread_mutex_lock()函数和pthread_mutex_trylock()函数的过程略有不同:

  • 当使用pthread_mutex_lock()函数进行加锁时,若此时已经被锁,则尝试加锁的线程会被阻塞,直到互斥锁被其他线程释放,当pthread_mutex_lock()函数有返回值时,说明加锁成功;

  • 而使用pthread_mutex_trylock()函数进行加锁时,若此时已经被锁,则会返回EBUSY的错误码。

同时,解锁的过程中,也需要满足两个条件:

  • 解锁前,互斥锁必须处于锁定状态;

  • 必须由加锁的线程进行解锁。

当互斥锁使用完成后,必须进行清除。

有了以上的准备,我们重新实现上述的多线程写操作,其实现代码如下所示:

#include <stdio.h> #include <pthread.h> #include <malloc.h>  pthread_mutex_t mutex;  const char filename[] = "hello";  void* thread(void *id){     int num = *(int *)id;    // 加锁     if (pthread_mutex_lock(&mutex) != 0){      fprintf(stdout, "lock error!\n");    }    // 写文件的操作    FILE *fp = fopen(filename, "a+");    int start = *((int *)id);    int end = start + 1;    setbuf(fp, NULL);// 设置缓冲区的大小    fprintf(stdout, "%d\n", start);    for (int i = (start * 10); i < (end * 10); i ++){       fprintf(fp, "%d\t", i);    }    fprintf(fp, "\n");    fclose(fp);     // 解锁    pthread_mutex_unlock(&mutex);    return NULL; }  int main(){    int num_thread = 5;    pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread);    int * id = (int *)malloc(sizeof(int) * num_thread);     // 初始化互斥锁    if (pthread_mutex_init(&mutex, NULL) != 0){      // 互斥锁初始化失败      free(pt);      free(id);      return 1;    }    for (int i = 0; i < num_thread; i++){       id[i] = i;       if (pthread_create(&pt[i], NULL, thread, &id[i]) != 0){          printf("thread create failed!\n");          return 1;       }    }    for (int i = 0; i < num_thread; i++){       pthread_join(pt[i], NULL);    }    pthread_mutex_destroy(&mutex);    // 释放资源    free(pt);    free(id);    return 0; }

最终的结果为:

Linux线程互斥锁的概念

“Linux线程互斥锁的概念”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: Linux线程互斥锁的概念

本文链接: https://www.lsjlt.com/news/281657.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Linux线程互斥锁的概念
    本篇内容介绍了“Linux线程互斥锁的概念”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在编程中,引入了对象互斥锁的概念,来保证共享数据操作...
    99+
    2023-06-15
  • Linux中线程互斥锁的示例分析
    小编给大家分享一下Linux中线程互斥锁的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!在编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个...
    99+
    2023-06-28
  • python多线程互斥锁与死锁
    目录一、多线程间的资源竞争二、互斥锁1.互斥锁示例2.可重入锁与不可重入锁三、死锁一、多线程间的资源竞争 以下列task1(),task2()两个函数为例,分别将对全局变量num加一...
    99+
    2022-11-13
  • Linux多线程中fork与互斥锁过程示例
    目录问题提出:(一)初次尝试(二)理性分析(三)解决问题(1)使用pthread_join()(2)使用phread_atfork()注册一个fork之前的判断问题提出: 我们有这样一个问题:在一个多线程程序中创建子进程...
    99+
    2022-06-04
    Linux多线程fork linux互斥锁过程
  • C++多线程之互斥锁与死锁
    目录1.前言2.互斥锁2.1 互斥锁的特点2.2 互斥锁的使用2.3 std::lock_guard3.死锁3.1 死锁的含义3.2 死锁的例子3.3 死锁的解决方法1.前言 比如说...
    99+
    2022-11-12
  • C#多线程中的互斥锁Mutex
    一、简介 Mutex的突出特点是可以跨应用程序域边界对资源进行独占访问,即可以用于同步不同进程中的线程,这种功能当然这是以牺牲更多的系统资源为代价的。 主要常用的两个方法: publ...
    99+
    2022-11-13
  • 【Linux】volatile | SIGCHLD | 多线程概念
    文章目录 1. volatile编译器优化 2.SIGCHLD信号验证SIGCHLD的存在 3. 多线程多线程概念理解概念什么是多线程调度成本低局部性原理 什么叫做进程 1. volatile 在vsc...
    99+
    2023-08-30
    linux 运维 服务器
  • python多线程互斥锁与死锁问题详解
    目录一、多线程共享全局变量二、给线程加一把锁锁三、死锁问题总结一、多线程共享全局变量 代码实现的功能: 创建work01与worker02函数,对全局变量进行加一操作创建main函数...
    99+
    2022-11-13
  • C#多线程中的互斥锁Mutex怎么用
    本篇内容主要讲解“C#多线程中的互斥锁Mutex怎么用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#多线程中的互斥锁Mutex怎么用”吧!一、简介Mutex的突出特点是可以跨应用程序域边界对...
    99+
    2023-06-30
  • python多线程中互斥锁与死锁的示例分析
    小编给大家分享一下python多线程中互斥锁与死锁的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一、多线程间的资源竞争以下列task1(),task2()两个函数为例,分别将对全局变量num加一重复一千万次循环(...
    99+
    2023-06-29
  • Go语言线程安全之互斥锁与读写锁
    目录一、互斥锁是什么?1.概念2.未加锁3.加锁之后二、读写锁【效率革命】1.为什么读写锁效率高2.使用方法三、sync.once1.sync.once产生背景2.sync.once...
    99+
    2022-11-13
  • Python互斥锁怎么解决多线程问题
    这篇文章给大家分享的是有关Python互斥锁怎么解决多线程问题的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。python主要应用领域有哪些1、云计算,典型应用OpenStack。2、WEB前端开发,众多大型网站均...
    99+
    2023-06-14
  • C++多线程互斥锁和条件变量的详解
    目录互斥锁:std::mutex::try_lock         条件变量:condition_variable总结我们了解互斥...
    99+
    2022-11-13
  • Linux的进程线程及调度的概念是什么
    这篇“Linux的进程线程及调度的概念是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Linux的进程线程及调度的概念是...
    99+
    2023-06-28
  • Java多线程编程的概念
    这篇文章主要讲解了“Java多线程编程的概念”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java多线程编程的概念”吧!Java多线程编程是什么?一个程序或进程能够包含多个线程,这些线程可以...
    99+
    2023-06-17
  • Linux互斥锁的实现原理是什么
    本篇内容主要讲解“Linux互斥锁的实现原理是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Linux互斥锁的实现原理是什么”吧!互斥锁(Mutex)是在原子操作API的基础上实现的信号量行...
    99+
    2023-06-28
  • java线程、进程和Synchronized的概念
    这篇文章主要介绍“java线程、进程和Synchronized的概念”,在日常操作中,相信很多人在java线程、进程和Synchronized的概念问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java线程、...
    99+
    2023-05-30
    java
  • Python实现的多线程同步与互斥锁功能示例
    本文实例讲述了Python实现的多线程同步与互斥锁功能。分享给大家供大家参考,具体如下: #! /usr/bin/env python #coding=utf-8 import threading im...
    99+
    2022-06-04
    示例 多线程 功能
  • linux线程间的同步与互斥知识点总结
    在线程并发执行的时候,我们需要保证临界资源的安全访问,防止线程争抢资源,造成数据二义性。 线程同步: 条件变量 为什么使用条件变量? 对临界资源的时序可控性,条件满足会通知其他等待操作临界资源的线程,类似信号。 ...
    99+
    2022-06-04
    linux 线程间 同步 互斥
  • 浅谈c++11线程的互斥量
    目录为什么需要互斥量独占互斥量std::mutex原子操作为什么需要互斥量 在多任务操作系统中,同时运行的多个任务可能都需要使用同一种资源。这个过程有点类似于,公司部门里,我在使用着...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作