线程同步有几种方法

线程同步有几种方法

线程同步方法有哪些?在linux下,系统提供了很多种方式来实现线程同步,其中最常用的便是互斥锁、条件变量和信号量这三种方式,可能还有很多伙伴对于这三种方法都不熟悉,下面就给大家详细介绍下。

Linux下实现线程同步的三种方法:

一、互斥锁(mutex)

通过锁机制实现线程间的同步。

1、初始化锁。在Linux下,线程的互斥量数据类型是pthread_mutex_t。在使用前,要对它进行初始化。

静态分配:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

动态分配:int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutex_attr_t *mutexattr);

2、加锁。对共享资源的访问,要对互斥量进行加锁,如果互斥量已经上了锁,调用线程会阻塞,直到互斥量被解锁。

int pthread_mutex_lock(pthread_mutex *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex);

3、解锁。在完成了对共享资源的访问后,要对互斥量进行解锁。

int pthread_mutex_unlock(pthread_mutex_t *mutex);

4、销毁锁。锁在是使用完成后,需要进行销毁以释放资源。

int pthread_mutex_destroy(pthread_mutex *mutex);

#include #include #include #include #include "iostream"using namespace std;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;int tmp;void* thread(void *arg){cout << "thread id is " << pthread_self() << endl;pthread_mutex_lock(&mutex);tmp = 12;cout << "Now a is " << tmp << endl;pthread_mutex_unlock(&mutex);return NULL;}int main(){pthread_t id;cout << "main thread id is " << pthread_self() << endl;tmp = 3;cout << "In main func tmp = " << tmp << endl;if (!pthread_create(&id, NULL, thread, NULL)){cout << "Create thread success!" << endl;}else{cout << "Create thread failed!" << endl;}pthread_join(id, NULL);pthread_mutex_destroy(&mutex);return 0;}//编译:g++ -o thread testthread.cpp -lpthread

相关推荐:《PHP入门教程》

二、条件变量(cond)

与互斥锁不同,条件变量是用来等待而不是用来上锁的。条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和互斥锁同时使用。条件变量分为两部分: 条件和变量。条件本身是由互斥量保护的。线程在改变条件状态前先要锁住互斥量。条件变量使我们可以睡眠等待某种条件出现。条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待“条件变量的条件成立”而挂起;另一个线程使“条件成立”(给出条件成立信号)。条件的检测是在互斥锁的保护下进行的。如果一个条件为假,一个线程自动阻塞,并释放等待状态改变的互斥锁。如果另一个线程改变了条件,它发信号给关联的条件变量,唤醒一个或多个等待它的线程,重新获得互斥锁,重新评价条件。如果两进程共享可读写的内存,条件变量可以被用来实现这两进程间的线程同步。

1、初始化条件变量。

静态态初始化,pthread_cond_t cond = PTHREAD_COND_INITIALIER;

动态初始化,int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);

2、等待条件成立。释放锁,同时阻塞等待条件变量为真才行。timewait()设置等待时间,仍未signal,返回ETIMEOUT(加锁保证只有一个线程wait)

清程爱画 清程爱画

AI图像与视频生成平台,拥有超丰富的工作流社区和多种图像生成模式。

清程爱画 170 查看详情 清程爱画

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);

3、激活条件变量。pthread_cond_signal,pthread_cond_broadcast(激活所有等待线程)

int pthread_cond_signal(pthread_cond_t *cond);

int pthread_cond_broadcast(pthread_cond_t *cond); //解除所有线程的阻塞

4、清除条件变量。无线程等待,否则返回EBUSY

int pthread_cond_destroy(pthread_cond_t *cond);

[cpp] view plain copy#include #include #include "stdlib.h"#include "unistd.h"pthread_mutex_t mutex;pthread_cond_t cond;void hander(void *arg){free(arg);(void)pthread_mutex_unlock(&mutex);}void *thread1(void *arg){pthread_cleanup_push(hander, &mutex);while(1){printf("thread1 is runningn");pthread_mutex_lock(&mutex);pthread_cond_wait(&cond, &mutex);printf("thread1 applied the conditionn");pthread_mutex_unlock(&mutex);sleep(4);}pthread_cleanup_pop(0);}void *thread2(void *arg){while(1){printf("thread2 is runningn");pthread_mutex_lock(&mutex);pthread_cond_wait(&cond, &mutex);printf("thread2 applied the conditionn");pthread_mutex_unlock(&mutex);sleep(1);}}int main(){pthread_t thid1,thid2;printf("condition variable study!n");pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond, NULL);pthread_create(&thid1, NULL, thread1, NULL);pthread_create(&thid2, NULL, thread2, NULL);sleep(1);do{pthread_cond_signal(&cond);}while(1);sleep(20);pthread_exit(0);return 0;}
#include #include #include "stdio.h"#include "stdlib.h"static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;struct node{int n_number;struct node *n_next;}*head = NULL;static void cleanup_handler(void *arg){printf("Cleanup handler of second thread./n");free(arg);(void)pthread_mutex_unlock(&mtx);}static void *thread_func(void *arg){struct node *p = NULL;pthread_cleanup_push(cleanup_handler, p);while (1){//这个mutex主要是用来保证pthread_cond_wait的并发性pthread_mutex_lock(&mtx);while (head == NULL){//这个while要特别说明一下,单个pthread_cond_wait功能很完善,为何//这里要有一个while (head == NULL)呢?因为pthread_cond_wait里的线//程可能会被意外唤醒,如果这个时候head != NULL,则不是我们想要的情况。//这个时候,应该让线程继续进入pthread_cond_wait// pthread_cond_wait会先解除之前的pthread_mutex_lock锁定的mtx,//然后阻塞在等待对列里休眠,直到再次被唤醒(大多数情况下是等待的条件成立//而被唤醒,唤醒后,该进程会先锁定先pthread_mutex_lock(&mtx);,再读取资源//用这个流程是比较清楚的pthread_cond_wait(&cond, &mtx);p = head;head = head->n_next;printf("Got %d from front of queue/n", p->n_number);free(p);}pthread_mutex_unlock(&mtx); //临界区数据操作完毕,释放互斥锁}pthread_cleanup_pop(0);return 0;}int main(void){pthread_t tid;int i;struct node *p;//子线程会一直等待资源,类似生产者和消费者,但是这里的消费者可以是多个消费者,而//不仅仅支持普通的单个消费者,这个模型虽然简单,但是很强大pthread_create(&tid, NULL, thread_func, NULL);sleep(1);for (i = 0; i n_number = i;pthread_mutex_lock(&mtx); //需要操作head这个临界资源,先加锁,p->n_next = head;head = p;pthread_cond_signal(&cond);pthread_mutex_unlock(&mtx); //解锁sleep(1);}printf("thread 1 wanna end the line.So cancel thread 2./n");//关于pthread_cancel,有一点额外的说明,它是从外部终止子线程,子线程会在最近的取消点,退出//线程,而在我们的代码里,最近的取消点肯定就是pthread_cond_wait()了。pthread_cancel(tid);pthread_join(tid, NULL);printf("All done -- exiting/n");return 0;}

三、信号量(sem)

如同进程一样,线程也可以通过信号量来实现通信,虽然是轻量级的。信号量函数的名字都以“sem_”打头。线程使用的基本信号量函数有四个。

1、信号量初始化。

int sem_init (sem_t *sem , int pshared, unsigned int value);

这是对由sem指定的信号量进行初始化,设置好它的共享选项(linux 只支持为0,即表示它是当前进程的局部信号量),然后给它一个初始值VALUE。

2、等待信号量。给信号量减1,然后等待直到信号量的值大于0。

int sem_wait(sem_t *sem);

3、释放信号量。信号量值加1。并通知其他等待线程。

int sem_post(sem_t *sem);

4、销毁信号量。我们用完信号量后都它进行清理。归还占有的一切资源。

int sem_destroy(sem_t *sem);

#include #include #include #include #include #include #define return_if_fail(p) if((p) == 0){printf ("[%s]:func error!/n", __func__);return;}typedef struct _PrivInfo{sem_t s1;sem_t s2;time_t end_time;}PrivInfo;static void info_init (PrivInfo* thiz);static void info_destroy (PrivInfo* thiz);static void* pthread_func_1 (PrivInfo* thiz);static void* pthread_func_2 (PrivInfo* thiz);int main (int argc, char** argv){pthread_t pt_1 = 0;pthread_t pt_2 = 0;int ret = 0;PrivInfo* thiz = NULL;thiz = (PrivInfo* )malloc (sizeof (PrivInfo));if (thiz == NULL){printf ("[%s]: Failed to malloc priv./n");return -1;}info_init (thiz);ret = pthread_create (&pt_1, NULL, (void*)pthread_func_1, thiz);if (ret != 0){perror ("pthread_1_create:");}ret = pthread_create (&pt_2, NULL, (void*)pthread_func_2, thiz);if (ret != 0){perror ("pthread_2_create:");}pthread_join (pt_1, NULL);pthread_join (pt_2, NULL);info_destroy (thiz);return 0;}static void info_init (PrivInfo* thiz){return_if_fail (thiz != NULL);thiz->end_time = time(NULL) + 10;sem_init (&thiz->s1, 0, 1);sem_init (&thiz->s2, 0, 0);return;}static void info_destroy (PrivInfo* thiz){return_if_fail (thiz != NULL);sem_destroy (&thiz->s1);sem_destroy (&thiz->s2);free (thiz);thiz = NULL;return;}static void* pthread_func_1 (PrivInfo* thiz){return_if_fail(thiz != NULL);while (time(NULL) end_time){sem_wait (&thiz->s2);printf ("pthread1: pthread1 get the lock./n");sem_post (&thiz->s1);printf ("pthread1: pthread1 unlock/n");sleep (1);}return;}static void* pthread_func_2 (PrivInfo* thiz){return_if_fail (thiz != NULL);while (time (NULL) end_time){sem_wait (&thiz->s1);printf ("pthread2: pthread2 get the unlock./n");sem_post (&thiz->s2);printf ("pthread2: pthread2 unlock./n");sleep (1);}return;}

以上便是Linux下实现线程同步常用的三种方法,大家都知道,线程的最大的亮点便是资源共享性,而资源共享中的线程同步问题却是一大难点。

以上就是线程同步有几种方法的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/551162.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月9日 20:10:17
下一篇 2025年11月9日 20:11:39

相关推荐

  • 快速祛除老年斑的有效方法(教你简单又快速消除老年斑的养肤秘诀)

    随着年龄的增长,老年斑通常出现在面部、颈部和手背等暴露部位,给人们的外貌带来困扰。它是一种常见的皮肤问题,让人看起来显老。为帮助您恢复年轻健康的肌肤,php小编子墨整理了一些有效祛除老年斑的方法。本文将分享快速简单的养肤秘诀,帮助您快速消除老年斑。 1.积极保护皮肤免受紫外线伤害的重要性 所以避免长…

    2025年12月5日
    000
  • 颈椎压迫神经的缓解方法(舒缓颈椎压迫神经的有效措施和建议)

    颈椎压迫神经是一种常见的健康问题,会导致颈部疼痛、麻木和肌肉无力。随着人们关注缓解颈椎压迫神经的方法,本文将提供一些经过验证的策略。php小编西瓜在这里将探讨这些缓解方法,帮助读者更好地应对这一问题。通过了解这些技巧,读者可以减轻颈部疼痛,改善神经功能,从而提高他们的整体健康和生活质量。 段落 1.…

    2025年12月5日
    000
  • 文件超过七天失效恢复方法(如何恢复超过七天失效的文件)

    在数字化时代,文件已成为我们不可或缺的一部分。 不幸的是,我们有时可能会丢失或删除宝贵的文件,而这些文件超过七天,无法通过回收站恢复。当这种情况发生时,您该如何恢复超过七天失效的文件?别担心,本文将为您提供一些实用的方法和技巧。php小编子墨将引导您了解如何找到专业的数据恢复软件、使用免费的数据恢复…

    2025年12月4日
    000
  • 如何选择手机膜,保护你的手机屏幕(选购手机膜的几大要点与技巧)

    随着智能手机的普及,手机膜已成为必不可少的配件,可以保护手机屏幕,延长其使用寿命。但市面上的手机膜琳琅满目,如何选择一款最适合自己的手机膜呢?php小编柚子将为您介绍选购手机膜的几大要点与技巧,帮助您避免踩坑,选出最适合的手机膜。 了解手机膜的材质及类型 PET膜,TPU等、手机膜有多种材质,包括钢…

    2025年12月3日
    000
  • 火影忍者手游须佐佐助口令兑换码

    火影忍者手游中,须佐佐助口令兑换码的获取与兑换%ignore_a_2%如下。 1、 火影忍者手游中,须佐佐助口令活动将在7月9日至7月23日进行。 2、 正确口令:忍界压路机(123456、须佐佐助辣条哥、须佐欧皇等)。 快剪辑 国内⼀体化视频⽣产平台 54 查看详情 以上就是火影忍者手游须佐佐助口…

    2025年12月3日 软件教程
    000
  • 四六级学籍照片上传方法

    如何上传四六级学籍照片 1、 首先,打开微信,进入城市服务公众号,如图所示。 2、 接着,在公众号的菜单栏底部找到便民服务,然后在弹出的窗口中点击微信版面,按照下图的操作步骤进行。 快剪辑 国内⼀体化视频⽣产平台 54 查看详情 3、 在办理业务的过程中选择学籍身份,随后上传学籍照片,具体位置如图所…

    2025年12月3日 软件教程
    000
  • mysql 常用几种密码恢复方法

    mysql 常用几种密码恢复方法/*一. MySQL密码的恢复方法之一 如果忘记了MySQL的root密码,可以用以下方法重新设置: 1. KILL掉系统里的MySQL进程;

    数据库 2025年12月2日
    000
  • mysql数据库备份方法

    mysql数据库备份方法mysql数据库备份方法有很多种,下面我们来一一介绍一下备份工具与直接在mysql.exe进行数据备份。

    数据库 2025年12月2日
    000
  • mysql 开启远程连接的三种方法

    本文章收藏了三种关于如何开启mysql 远程连接,第一款就是在mysql cmd命令提示符下给mysql开启远程连接的,方法三是修改mysql my.ini的文件配置来修改的哦。

    数据库 2025年12月2日
    000
  • Mysql删除重复的数据的方法

    这篇文章主要介绍了mysql删除重复的数据 mysql数据去重复,需要的朋友可以参考下 MySQL数据库中查询重复数据 select * from employee group by emp_name having count (*)>1; Mysql  查询可以删除的重复数据 启科网络PHP…

    2025年12月2日
    000
  • mysql去重的两种方法实例详解

    这篇文章主要介绍了%ignore_a_1%去重的两种方法详解及实例代码的相关资料,这里对去重的两种方法进行了一一实例详解,需要的朋友可以参考下 mysql去重 方法一:     在使用MySQL时,有时需要查询出某个字段不重复的记录,虽然mysql提供 有distinct这个关键字来过滤掉多余的重复…

    2025年12月2日
    000
  • mysql中的跨库关联查询方法详解

    这篇文章主要介绍了mysql中的跨库关联查询方法,需要的朋友可以参考下 业务场景:关联不同数据库中的表的查询 比如说,要关联的表是:机器A上的数据库A中的表A && 机器B上的数据库B中的表B。 这种情况下,想执行“select A.id,B.id from A left join …

    2025年12月2日 数据库
    000
  • mysql去重的方法

    这篇文章主要介绍了mysql去重的方法整理的相关资料,需要的朋友可以参考下 MySQL去重的方法整理 【初级】有极少的重复行 使用distinct查出来,然后手动一行一行删除。 【中级】按照单个字段的重复去重 例如:对id字段去重 使用方法:获取id的重复字段的值,利用相同id字段所在的行中,比较出…

    2025年12月2日
    000
  • mysql中多表不关联查询的实现方法详解

    下面小编就为大家带来一篇浅谈mysql中多表不关联查询的实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧 大家在使用MySQL查询时正常是直接一个表的查询,要不然也就是多表的关联查询,使用到了左联结(left join)、右联结(right join)、内联结(…

    2025年12月2日
    000
  • php调用mysql存储过程的方法

    php调用mysql存储过程的方法在网上找了很久没找到好的关于php调用mysql存储过程的方法,我就自己来写一个简单的关于调用mysql存储过程实例吧,讲得不好,如果你有意见可以自己写

    数据库 2025年12月2日
    000
  • mysql导入存储过程的方法

    mysql导入存储过程的方法本文章提供二种关于mysql导入存储过程的方法与mysql存储过程导出方法,下面我们先来看看导出存储过程的实例,再看一款详细的导入存储过程方法。导出mysql里面的函数或者存储过程

    数据库 2025年12月2日
    000
  • mysql limit 优化方法与详细说明(1/3)

    LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。LIMIT 接受一个或两个数字参数。参数必须是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目。初始记录行的偏移量是 0(而不是 1):

    数据库 2025年12月2日
    000
  • mysql创建数据库几种方法

    现在很流行mysql php组合了,下面我们来总结几种关于mysql创建数据库方法,因为创建数据库很简单,所以我们也就快速的讲一下,

    数据库 2025年12月2日
    000
  • mysql升级后不能启动 的解决方法

    mysql升级后不能启动的解决方法 一。 1 .下载http: //files.directadmin.com/services/all/mysql/mysql-5.1.50.tar.gz 2 .tarzxvfmysql- 5.1 . 50 .tar.gz 3 .cpmysql- 5.1 . 50 …

    数据库 2025年12月2日
    000
  • php中获取系统信息的方法

    “系统信息”工具收集系统信息(如计算机中安装的设备或计算机中加载的设备驱动程序),并提供用于显示关联的系统主题的菜单。 您可使用该工具来诊断计算机问题。 例如,如果您遇到显示问题,则可使用该工具来确定计算机上安装的显示卡并查看它的驱动程序的状况。 本篇文章是对php中获取系统信息的方法进行了详细的分…

    2025年12月2日
    000

发表回复

登录后才能评论
关注微信