linux线程同步教程,多线程同步

1.linux使用多线程同步的方法

1)互斥锁:当线程A锁定了互斥变量时,线程B再去锁定时就会被挂起,直到A解锁。

注意:当线程要不断的去轮询检查某个条件以判断是否可以操作需同步的数据时,可使用条件变量提高效率。

demo如下:

#include

#include

#include

pthread_mutex_t mutex;

void *print_msg(void *arg)

{

int i = 0;

pthread_mutex_lock(&mutex); //互斥锁加锁

for (i = 0; i < 20; i++)

{

printf(" i = %d\n", i);

usleep(200);

}

pthread_mutex_unlock(&mutex);

}

int main()

{

pthread_t id1, id2;

pthread_mutex_init(&mutex, NULL);

pthread_create(&id1, NULL, print_msg, NULL);

pthread_create(&id2, NULL, print_msg, NULL);

pthread_join(id1, NULL); //使主线程等待该线程结束后才结束,否则主线程很快结束,该线程没有机会执行

pthread_join(id2, NULL);

pthread_mutex_destroy(&mutex);

return 0;

}

2)信号量:实际是一个整数,只要信号量的value大于0,其他线程就可以sem_wait成功,成功后信号量的value减1。若value值不大于0,则sem_wait使得线程阻塞,直到sem_post释放后value值加1,但是sem_wait返回之前还是会将此value值减1。

demo如下:

#include

#include

#include

#include

#include

#include

void *thread_func(void* msg);

sem_t sem;

sem_t sem_add;

#define MSG_SIZE 512

int main()

{

int res = -1;

pthread_t thread;

void *thread_result = NULL;

char msg[MSG_SIZE];

res = sem_init(&sem, 0, 0);

if (res == -1)

{

printf("sem init failed\n");

exit(-1);

}

res = sem_init(&sem_add, 0, 1);

if (res == -1)

{

printf("sem_add init failed\n");

exit(-1);

}

res = pthread_create(&thread, NULL, thread_func, msg);

if (res != 0)

{

printf("pthread_create failed\n");

exit(-1);

}

printf("input some text. Enter 'end' to finish...\n");

sem_wait(&sem_add);

while(strcmp("end\n", msg) != 0)

{

if (strncmp(msg, "TEST", 4) == 0)

{

strcpy(msg, "copy_data\n");

sem_post(&sem);

sem_wait(&sem_add);

}

fgets(msg, MSG_SIZE, stdin);

sem_post(&sem); //sem信号量加1,让子线程开始执行

sem_wait(&sem_add); //sem_add信号量减1,等待子线程处理完成

}

printf("waiting for thread to finish...\n");

res = pthread_join(thread, &thread_result);

if (res != 0)

{

printf("pthread_join faild\n");

exit(-1);

}

printf("thread joined\n");

sem_destroy(&sem);

sem_destroy(&sem_add);

exit(0);

return 0;

}

void* thread_func(void* msg)

{

char *ptr = (char*)msg;

sem_wait(&sem);

while(strcmp("end\n", ptr) != 0)

{

int i = 0;

for (; ptr[i] != '\0'; ++i )

{

if (ptr[i] >= 'a' && ptr[i] <= 'z')

{

ptr[i] -= 'a' - 'A';

}

}

printf("you input %d characters\n", i - 1);

printf("to uppercase: %s\n", ptr);

sem_post(&sem_add);

sem_wait(&sem);

}

sem_post(&sem_add);

pthread_exit(NULL);

}

3)条件变量:经常和互斥锁一起使用,使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程会解开相应的互斥锁并等待条件发生变化,一旦其他的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此变量阻塞的线程,这些线程将重新锁定互斥锁并重新测试条件是否满足。

pthread_cont_init()

pthread_cont_destroy()

pthread_cont_wait() //线程解开mutex指向的锁并被条件变量阻塞

pthread_cont_timedwait() //多了时间参数,当时间过了以后,即使条件变量不满足,阻塞也被解除

pthread_cont_signal()/pthread_cont_broadcast //唤醒被条件变量阻塞的线程。

demo如下:

pthread1()

{

pthread_mutex_lock(lock_s);

sum++;

pthread_mutex_unlock(lock_s);

if (sum >= 100)

{

pthread_cond_signal(&cond_sum_ready);//先发送一次

}

}

pthread2()

{

pthread_mutex_lock(lock_s);

while(sum < 100)

{

pthread_cond_wait(&cond_sum_ready, &lock_s);//会先执行pthread_MUTEX_UNLOCK进行解锁,然后休眠

}

sum = 0;

pthread_mutex_unlock(lock_s);

}

注意:最终哪个线程接收到信号,根据优先级来

4)读写锁:可以多个线程同时占用读模式的读写锁,但是只能一个线程占用写模式的读写锁。

当读写锁是写加锁状态时,在这个锁被解锁前,所有试图对这个锁加锁的线程都会被阻塞;

当读写锁是读加锁状态时,其他线程可以读模式得到访问权,但是以写模式对它进行加锁的线程都将被阻塞;

当读写锁是在读模式加锁状态时,如果有其他线程试图以写模式加锁,读写锁通常会阻塞随后的读模式锁请求,避免读模式锁长期占用,而写模式所长期阻塞;

读写锁适用于对数据读的次数比写的次数多的情况。

API接口:

初始化和销毁:

int pthread_rwlock_init();

int pthread rwlock_destroy();

读加锁、写加锁、解锁:

pthread_rwlock_rdlock();

pthread_rwlock_wrlock();

pthread_rwlock_unlock();

非阻塞获得读锁和写锁:

pthread_rwlock_tryrdlock();

pthread_rwlock_trywrlock();

demo如下

#include

#include

#include

#define Read_Num 2

pthread_rwlock_t lock;

class Data

{

public:

Data(int i, float f): I(i), F(f){}

int GetI()

{

return I;

}

float GetF()

{

return F;

}

private:

int I;

float F;

};

Data *pData = NULL;

void *read(void *arg)

{

int *id = (int*)arg;

while(true)

{

pthread_rwlock_rdlock(&lock);

printf(" reader %d is reading data\n", *id);

if (pData == NULL)

{

printf("data is NULL\n");

}

else

{

printf("data: I = %d, F = %f\n", pData->GetI(), pData->GetF());

}

pthread_rwlock_unlock(&lock);

}

pthread_exit(0);

}

void *write(void *arg)

{

while(true)

{

pthread_rwlock_wrlock(&lock); //写锁加锁后,解锁前,所有试图对该锁加锁的线程都会被堵塞

printf("writer is wiriting data:\n");

if (pData == NULL)

{

pData = new Data(2, 2.2);

printf("writer is writing data: %d, %f\n", pData->GetI(), pData->GetF());

}

else

{

delete pData;

pData = NULL;

printf("wirter free the data\n");

}

pthread_rwlock_unlock(&lock);

}

pthread_exit(0);

}

int main()

{

pthread_t reader[Read_Num];

pthread_t writer;

for (int i = 0; i < Read_Num; i++)

{

pthread_create(&reader[i], NULL, read, (void*)&i);

}

pthread_create(&writer, NULL, write, NULL);

while(1)

{

sleep(1);

}

return 0;

}

2.信号量和互斥锁之间的区别:

互斥锁用于互斥,对资源的访问是无序的,信号量用于同步,对资源的访问是有序的

互斥量的加锁和解锁必须由同一线程对应使用,而信号量可以由一个线程释放,另一个线程得到

3.什么情况下会产生死锁以及怎样避免死锁

比如线程A,对资源M加锁,去申请资源N;

线程B,对资源N加锁,去申请资源M;

此种情况下会产生死锁,要有效的避免死锁,可使用银行家算法:

线程A和B在使用资源的时候按照同一顺序,即加锁时按照同一顺序,这样就可以避免死锁。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/554220.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为什么谷歌浏览器打不开 Google Chrome打不开解决方法

核心提示&#xff1a;很多用户反映有谷歌浏览器打不开状况&#xff0c;下面小编就为大家分享一个解决方法。 谷歌浏览器它是又Google(谷歌)公司开发的免费网页浏览器。它在全球拥有大量用户群体。很多用户反映有谷歌浏览器打不开状况&#xff0c;下面小编就为大家分享一个解决…

linux 串口信息记到日志,[linux学习笔记]之一:ubuntu ch340调试备忘

[linux学习笔记]之一&#xff1a;ubuntu ch340调试备忘已有 2183 次阅读2016-11-8 21:52|个人分类:linux最近迷上了Linux&#xff0c;入了一块板。电脑使用win7ubuntu 双系统&#xff0c;可是调试的时候就麻烦了&#xff0c;ubuntu下写好sd卡镜像&#xff0c;调试的时候还要切换…

Chrome 69正式版浏览器遭批 恢复完整显示域名

Chrome 69正式版浏览器遭批 恢复完整显示域名 日前&#xff0c;谷歌发布了全新的Chrome 69正式版浏览器&#xff0c;带来了全新的材料设计等特性&#xff0c;也算是庆祝chrome浏览器10周年。不过&#xff0c;新版Chrome隐藏域名中的“www”遭到了用户批评&#xff0c;并认为会…

微软协助谷歌开发ARM平台Chrome浏览器

微软协助谷歌开发ARM平台chrome浏览器 美国科技博客9to5xx发现&#xff0c;&#xff0c;近日&#xff0c;微软的一些工程师正在为谷歌Chrome浏览器贡献代码&#xff0c;帮助其成为ARM平台上的原生Windows应用。 此外&#xff0c;高通高管上月表示&#xff0c;高通也正努力将原…

嵌入式linux 配置usb otg,嵌入式linux系统环境下USB设备的驱动实现

0 引言嵌入式linux系统环境以其易于移植裁减、内核小、效率高、完整、原代码开放及性能优异等特点&#xff0c;在嵌入式领域得到了非常广泛的应用。Linux的USB设备端的源代码中主要有USB device的海量存储设备、串口设备、网络设备等设备驱动程序及各种USB device控制器芯片的…

android Chrome浏览器快捷键

核心提示&#xff1a;在本教程中将为你介绍android Chrome浏览器快捷键! 众所周知&#xff0c;Google Android系统中内置的网页浏览器是桌面版Chrome浏览器的简化版本Chrome Lite&#xff0c;同样采用了开源的Webkit核心&#xff0c;安卓中文网整理了适用于搭载实体键盘G1的Ch…

linux 裸设备使用,linux裸设备使用

一、配置&#xff1a;RHAS4:1&#xff0c;将硬盘分区&#xff1a;#fdisk -l#fdisk /dev/sdb2&#xff0c;绑定&#xff1a;方式一&#xff1a;#raw /dev/raw/rawN /dev/sdbN#raw -qa#vi /etc/rc.localraw /dev/raw/rawN /dev/sdbN方式二&#xff1a;#vi /etc/sysconfig/rawdevi…

在iOS设备上如何使用Chrome浏览器的书签

核心提示&#xff1a;谷歌Chrome浏览器iOS版正式登陆AppStore。不过有很多人安装以后没有找到书签工具&#xff0c;以为没有。其实不然。iOS设备上的Chrome浏览器是内置有书签工具的&#xff0c;和Safari相比&#xff0c;不是很明显。只有搭配相应的App时&#xff0c;才能体现出…

linux p7zip密码,linux下7zip使用方法

现在流行的压缩软件有WIN平台下的winrar, winzip。Linux下则是bzip2, gzip等等。现在有一个叫做7z的压缩软件&#xff0c;号称是目前压缩比最大的软件。WIN平台下使用的是图形界面&#xff0c;使用方法和winrar差不了多少。但是在Linux下&#xff0c;7z可以使用的是命令行方式。…

下载腾讯视频里的视频_手机腾讯视频如何升级新版本

软件是否好用&#xff0c;还得大家下载腾讯视频安装才知道。本文分享怎么下载腾讯视频里的视频_手机腾讯视频如何升级新版本腾讯视频升级新版本。腾讯视频电影频道拥有大量高清在线电影资源&#xff0c;热门高清电影、好评电影、电影预告都可以在线观看&#xff0c;不去电影院也…

linux 上下文切换监控,[Linux] 查看进程的上下文切换pidstat

各个进程之间是共享 CPU 资源的&#xff0c;在不同的时候进程之间需要切换&#xff0c;让不同的进程可以在 CPU 执行&#xff0c;那么这个一个进程切换到另一个进程运行&#xff0c;称为进程的上下文切换。进程是由内核管理和调度的&#xff0c;所以进程的切换只能发生在内核态…

爱奇艺怎么看不了电视剧和视频

不管这个爱奇艺好用与否&#xff0c;都有一大批用户&#xff0c;本文小编分享“爱奇艺怎么看不了电视剧和视频”。爱奇艺客户端为您推荐更多精选热门视频&#xff0c;通过多条件筛选快速定位匹配结果&#xff0c;提供多种画质、多种语言切换播放和下载&#xff0c;支持边下载边…

linux arm9视频哪个好,谈谈ARM7与ARM9的区别

本文是写给准备学习ARM技术&#xff0c;而又没想好要学ARM7还是ARM9或者对ARM7与ARM9的区别不是很了解的初学者。希望本文对你们有点用处。由于职业的关系&#xff0c;经常会回答一些ARM初学者的问题&#xff0c;虽然问题千奇百怪&#xff0c;但以下两个问题绝对很有代表性。AR…

腾讯视频如何退出登陆

本文给大家整理了腾讯视频如何退出登陆方面的内容。腾讯视频支持在线进行加载&#xff0c;离线观看。 有时候我们要用一下别人的腾讯账号&#xff0c;这个时候就需要我们退出当前的账号&#xff0c;那么腾讯视频如何退出登陆呢?接下来我告诉大家~ 1、首先找到腾讯视频并打开…

linux通过yum安装nginx,Linux系统使用yum安装nginx教程

首先执行以下命令安装2个软件包&#xff1a;yum install epel-releaseyum install yum-utils然后新增yum源&#xff1a;vim /etc/yum.repos.d/nginx.repo写入以下内容&#xff1a;[nginx-stable]namenginx stable repobaseurlhttp://nginx.org/packages/centos/$releasever/$ba…

Chrome谷歌浏览器私密浏览自动开启功能获批专利

Chrome谷歌浏览器私密浏览自动开启功能获批专利 谷歌近日被授予一项新的专利&#xff1a;在桌面和移动浏览器中自动启用匿名浏览功能。谷歌这项美国专利号是8935798 B1&#xff0c;专利描述为用户使用浏览器上网&#xff0c;自动阻止浏览器存储浏览历史记录/用户输入文字&#…

linux怎么休眠快捷键,在Deepin系统中创建右键休眠选项的方法

本文介绍在深度Deepin操作系统中创建右键休眠选项&#xff0c;以方便你更快的进入到系统休眠当中&#xff0c;实现方法非常简单&#xff0c;按照下面的步骤进行就可以了。休眠的好处系统休眠&#xff0c;可以让平时的工作环境保存到硬盘中&#xff0c;以便开机后便可立即进入工…

谷歌Chrome 81浏览器更新:新增微软Chromium版Edge现代Web控件

谷歌浏览器是一款非常好用的服务软件&#xff0c;有很多用户都会选择这款软件进行搜索&#xff0c;这里有非常多的搜索功能&#xff0c;用户可以使用这款软件解决自己的一些难题&#xff0c;这款软件的功能也在不断的更新&#xff0c;用户可以使用手机在这里享受非常便捷的服务…

linux spoon.sh闪退,解决Linux Kettle出现闪退问题

linux环境&#xff0c; 运行sh spoon.sh打开图形化界面时经常出现闪退情况。报错信息如下&#xff1a;cfgbuilder - Warning: The configuration parameter [org] is not supported by the default configuration builder for scheme: sftpjava: cairo-misc.c:380: _cairo_oper…

Chrome浏览器占用太多内存,内存不够用怎么办

用户在使用浏览器打开每一个页面的时候都会有很多进程车程序&#xff0c;来保护用户的信息安全&#xff0c;每一个标签都有各自的运行方式&#xff0c;这样在使用的时候就可以达到互不干扰的效果&#xff0c;但是这样做就会将所有的数据都堆叠在一起&#xff0c;使用起来会有弊…