-
互斥锁的使用
2020-11-18 11:44:29这里简单介绍互斥锁的使用 互斥锁变量类型 pthread_mutex_t 互斥锁初始化 动态初始化 int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr); 参数说明: ...本文简单介绍互斥锁的使用
互斥锁变量类型
pthread_mutex_t
1.互斥锁初始化
1.1 动态初始化 需要销毁
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
参数说明:
mutex:传入互斥锁的地址
attr:属性,一般传递NULL采用默认属性
1.2 静态初始化 不需要销毁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
PTHREAD_MUTEX_INITIALIZER :宏定义了一个结构体的值
2.加锁
1.1 阻塞的加锁接口
int pthread_mutex_lock(pthread_mutex_t *mutex);
mutex:传入互斥锁的地址
如果mutex中计数器值为1,则pthread_mutex_lock接口直接返回,表示加锁成功,同时mutex中的计数器的值会被置为0
如果mutex中计数器值为0,则pthread_mutex_lock接口会阻塞在函数内部中,直到加锁成功
1.2 非阻塞加锁接口
int pthread_mutex_trylock(pthread_mutex_t *mutex);
mutex:传入互斥锁的地址
当mutex中的计数器值为1,则加锁成功直接返回
当mutex中的计数器值为0,也会返回,但是这时候没有加锁成功,所以不能访问临界资源
1.3 带有超时时间的加锁接口
int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,
const struct timespec *restrict abs_timeout);mutex:传入互斥锁的地址,abs_timeout : 等待的时间
1.带有超时时间的加锁接口,当没有获取互斥锁时,会等待abs_timeout时间,在这段时间中加锁成功了,就直接返回,如果等待超时,就直接返回,但是表示加锁失败了,需要循环使用进行加锁
注意:非阻塞接口一般都是配合循环使用
3.解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
mutex:传入互斥锁的地址
1.不管是使用哪个接口进行加锁的互斥锁都可以通过这个接口进行解锁
2.解锁的时候,会将互斥锁中的计时器的值置为1,表示其它线程可以获取这个互斥锁
4.互斥锁的销毁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
mutex:传入互斥锁的地址
针对动态初始化的互斥锁进行销毁
5.互斥锁的应用
这是一个黄牛抢票程序,4个工作线程代表4个黄牛,临界资源代表票,规则为:一张票只能被一个黄牛拿到。
#include <stdio.h> #include <unistd.h> #include <pthread.h> #define THREADCOUNT 4 // 票 int g_titcks = 100; //定义一个互斥锁‘ pthread_mutex_t g_lock; void* func(void* arg) { (void* ) arg; while(1) { //加锁 pthread_mutex_lock(&g_lock); if( g_titcks > 0) { printf("i am work thread %p , i have titck %d\n",pthread_self(), g_titcks); g_titcks--; } else { //解锁 pthread_mutex_unlock(&g_lock); break; } //解锁 pthread_mutex_unlock(&g_lock); } return NULL; } int main() { pthread_t tid[THREADCOUNT]; //互斥锁初始化 pthread_mutex_init(&g_lock,NULL); for(int i = 0; i < THREADCOUNT; i++) { int ret = pthread_create(&tid[i], NULL, func, NULL); if(ret < 0 ) { perror("pthread_ create \n"); return -1; } } for(int i = 0; i < THREADCOUNT; i++) { pthread_join(tid[i],NULL); } //互斥锁销毁 pthread_mutex_destroy(&g_lock); return 0; }
-
qt互斥锁的使用
2019-12-01 18:15:54qt互斥锁的使用 class CallbackStorage { public: int insertCallback(const QJSValue &callback) { QMutexLocker locker(&m_mtx); const int nextId = qMax(++m_counter, 0); ...qt互斥锁的使用
class CallbackStorage { public: int insertCallback(const QJSValue &callback) { QMutexLocker locker(&m_mtx); const int nextId = qMax(++m_counter, 0); if (nextId == 0) m_counter = 1; m_callbacks.insert(nextId, callback); return nextId; } QJSValue takeCallback(int callbackId) { QMutexLocker lock(&m_mtx); return m_callbacks.take(callbackId); } private: QMutex m_mtx; int m_counter; QHash<int, QJSValue> m_callbacks; }; } // namespace
-
MFC多线程互斥锁的使用
2019-10-04 23:14:12MFC多线程互斥锁的使用 本例演示在MFC中使用多线程。第一部分实现多线程的开启、暂停、继续、注销(见上一篇文章MFC多线程的开启、暂停、继续和注销)。第二部分实现两个线程互斥锁的使用。 演示系统为Win10,平台为...MFC多线程互斥锁的使用
本例演示在MFC中使用多线程。第一部分实现多线程的开启、暂停、继续、注销(见上一篇文章MFC多线程的开启、暂停、继续和注销)。第二部分实现两个线程互斥锁的使用。
演示系统为Win10,平台为VS2017(MFC),主要使用类为CWinThread。第二部分:
1.在原有基础上(见上一篇文章MFC多线程的开启、暂停、继续和注销)添加一个EDIT控件和一个线程MyThread2。
2.在ThreadTestDlg.h头文件中添加函数及变量声明:static UINT MyThread2(LPVOID* pParam);//线程函数 CWinThread *Thread2;//线程2
3.在ThreadTestDlg.cpp实现文件上部中添加变量:
CMutex Mutex;//用于互斥锁
修改文件末尾线程1函数定义:
//线程1函数 UINT CThreadTestDlg::MyThread1(LPVOID* pParam) { CThreadTestDlg *ap1 = (CThreadTestDlg *)pParam;//获取主类指针,在多线程类中使用主类变量需要使用指针ap1-> CSingleLock singleLock(&Mutex); while(1) { if (ThreadKill) { DWORD dwExitCode;//指定线程的退出代码 GetExitCodeThread(ap1->Thread1, &dwExitCode);//获取线程1的退出代码 AfxEndThread(dwExitCode, TRUE);//退出线程 } else { //singleLock.Lock();//没被调用就上锁自己用,已被调用就等着 //if (singleLock.IsLocked()) { n=1; strn.Format(_T("%d"), n); ap1->SetDlgItemText(IDC_EDIT1, strn); Sleep(30); } //singleLock.Unlock();//解锁 } } return 0; }
4.添加线程2函数定义:
UINT CThreadTestDlg::MyThread2(LPVOID* pParam) { CThreadTestDlg *ap2 = (CThreadTestDlg *)pParam;//获取主类指针,在多线程类中使用主类变量需要使用指针ap1-> CSingleLock singleLock(&Mutex); while (1) { if (ThreadKill) { DWORD dwExitCode;//指定线程的退出代码 GetExitCodeThread(ap2->Thread2, &dwExitCode);//获取线程2的退出代码 AfxEndThread(dwExitCode, TRUE);//退出线程 } else { //singleLock.Lock();//没被调用就上锁自己用,已被调用就等着 //if (singleLock.IsLocked()) { n=-1; strn.Format(_T("%d"), n); ap2->SetDlgItemText(IDC_EDIT2, strn); Sleep(30); } //singleLock.Unlock();//解锁 } } return 0; }
5.修改按钮响应函数:
void CThreadTestDlg::OnBnClickedButton1() { n = 0; ThreadKill = FALSE; Thread1 = AfxBeginThread((AFX_THREADPROC)MyThread1, this);//启动线程 Thread2 = AfxBeginThread((AFX_THREADPROC)MyThread2, this);//启动线程 } void CThreadTestDlg::OnBnClickedButton2() { Thread1->SuspendThread(); //暂停线程 Thread2->SuspendThread(); //暂停线程 } void CThreadTestDlg::OnBnClickedButton3() { Thread1->ResumeThread(); //继续线程 Thread2->ResumeThread(); //继续线程 } void CThreadTestDlg::OnBnClickedButton4() { ThreadKill = TRUE;// Thread1->ResumeThread(); //调用继续线程,排除线程处于暂停模式无法注销的情况。若线程处于工作状态,调用此函数无作用。 Thread2->ResumeThread(); //调用继续线程,排除线程处于暂停模式无法注销的情况。若线程处于工作状态,调用此函数无作用。 }
6.编译运行。这是未加互斥锁的情况下,程序中,我们在线程1将n赋值为1并在EDIT1显示;在线程2中将同一个变量n赋值为-1并在EDIT2显示。理论上控件上应分别显示1和-1,但实际上,会出现同时显示1,或同时显示-1或显示-1和1的情况。这是由于线程间同时调用同一变量造成的(严格来讲并不是同时,而是比如线程1赋值为1后还没打印出来就被线程2赋值为-1了,所以造成最后打印出来都是-1,其他情况同理)。
7.互斥锁使用。上面修改中其实已经加入了互斥锁的必要说明,只需要把注销掉的代码复原即可实现。实际操作步骤如下:
①添加类变量声明CMutex Mutex;//用于互斥锁
②在线程中定义互斥锁类变量
CSingleLock singleLock(&Mutex);
③在线程中添加处理代码
singleLock.Lock();//没被调用就上锁自己用,已被调用就等着 if (singleLock.IsLocked()) { //在此添加处理代码 } singleLock.Unlock();//解锁
8.修改后编译运行,可以看到使用互斥锁后,程序按预想的形式运行,EDIT1稳定的显示1,EDIT2稳定的显示-1。
9.使用互斥锁后,当进入线程1时会先检查变量是否被调用,没有的话就上锁给自己用,待自己用完再解锁,如果变量已经被调用上锁了,那么久等待变量释放。这样在一个线程的运行周期内,其他线程就无法更改变量。 -
Linux互斥锁的使用
2020-08-28 23:12:09目录 互斥锁原理 1. 互斥锁原理 如上图所示:如果多个线程要访问一段共享资源的内存区域时,其中一个线程(如图中线程1)首先读取共享区域时,会在共享区域外设置一把互斥锁,其它线程阻塞...2. 互斥锁的相关函数目录
1. 互斥锁原理
如上图所示:如果多个线程要访问一段共享资源的内存区域时,其中一个线程(如图中线程1)首先读取共享区域时,会在共享区域外设置一把互斥锁,其它线程阻塞在互斥锁处,线程1结束共享资源的访问后,会解锁该内存区域,此时其它的线程才可以继续访问共享资源的内存区域。本来多线程访问数据时是并行访问内存区域的,加上互斥锁后变为串行处理。
多线程编程是建议使用互斥锁,这样可以对公共区域的数据进行保护。互斥锁的缺点就是串行,数据访问的效率会有一定的降低。
2. 互斥锁相关函数
1.创建互斥锁函数 pthread_mutex_t mutex; 2.初始化互斥锁函数: int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr ); 参数1:传出参数,调用是创建的互斥锁变量。 参数2:传入参数,互斥锁属性,一般为NULL表示为默认属性 这里的restrict关键字,表示指针指向的内容只能通过这个指针进行修改 restrict关键字作用可以理解为: 用来限定指针变量。被该关键字限定的指针变量所指向的内存操作,必须由本指针完成。 初始化可以使用静态初始化和动态初始化,示例: pthread_mutex_t mutex; 1. pthread_mutex_init(&mutex, NULL); 动态初始化。 2. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 静态初始化。 3.加锁 int pthread_mutex_lock(pthread_mutex_t *mutex); 参数:mutex 没有上锁,当前线程会将这把锁上锁 已经上锁,当前线程会阻塞在此 锁被打开之后,线程会解除阻塞 4.尝试加锁 int pthread_mutex_trylock(pthread_mutex_t *mutex); 参数:mutex 没有上锁:同上 已经上锁,不阻塞返回 5.解锁 int pthread_mutex_unlock(pthread_mutex_t *mutex); 6.销毁一个互斥锁 int pthread_mutex_destroy(pthread_mutex_t *mutex);
3. 互斥锁使用过程
(1)创建互斥锁:pthread_mutex_t mutex;
(2)初始化互斥锁: pthread_mutex_init(&mutex, NULL);
(3)找到线程共同操作的共享资源
加锁:prhread_mutex_lock(&mutex); //如果共享区域已经上锁,会阻塞线程
pthread_mutex_trylock(&mutex); //如果共享区域已经上锁,直接返回,不会阻塞。
(4)访问内存区域
(5)解锁:pthread_mutex_unlock(&mutex);
(6)销毁:pthread_mutex_destory(&mutex);
使用注意:
尽量保证锁的粒度,越小越好,一般访问共享数据前加锁,访问结束立即解锁。
互斥锁,本质是结构体。 我们可以看成整数。 初值为 1。(pthread_mutex_init() 函数调用成功。)
加锁: --操作, 阻塞线程。
解锁: ++操作, 唤醒阻塞在锁上的线程。
try锁:尝试加锁,成功--。失败,返回。同时设置错误号 EBUSY
4. 互斥锁使用示例
pthread_mutex.c:主线程建立两个子线程对全局变量进行++操作。
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <pthread.h> #define MAX 10000 // 全局变量 int number; //创建一把互斥锁 pthread_mutex_t mutex; // 线程A处理函数 void* funcA_num(void* arg) { for(int i=0; i<MAX; ++i) { //访问全局变量之前加锁 //如果mutex被锁上了,代码阻塞在当前位置 pthread_mutex_lock(&mutex); int cur = number; cur++; number = cur; printf("Thread A, id = %lu, number = %d\n", pthread_self(), number); //解锁 pthread_mutex_unlock(&mutex); usleep(10); } return NULL; } // 线程B处理函数 void* funcB_num(void* arg) { for(int i=0; i<MAX; ++i) { pthread_mutex_lock(&mutex); int cur = number; cur++; number = cur; printf("Thread B, id = %lu, number = %d\n", pthread_self(), number); pthread_mutex_unlock(&mutex); usleep(10); } return NULL; } /*主函数创建两个线程,分别操作共享区域内存:全局变量number*/ int main(int argc, const char* argv[]) { pthread_t p1, p2; //初始化互斥锁 pthread_mutex_init(&mutex,NULL); // 创建两个子线程 pthread_create(&p1, NULL, funcA_num, NULL); pthread_create(&p2, NULL, funcB_num, NULL); // 阻塞,资源回收 pthread_join(p1, NULL); pthread_join(p2, NULL); //释放互斥锁资源 pthread_mutex_destroy(&mutex); return 0; }
运行结果:AB两个线程逐个访问共享内存区域。
5. 死锁
程序运行是要避免死锁的情况。通常出现死锁的情况有两种:
1. 对一个锁反复lock:对一个地方使用了两次锁,没有及时解锁2. 两个线程,各自持有一把锁,请求另一把锁,如下图所示:A,B两个线程访问AB两个共享数据区域时。
解决方法:
1. 让线程按照一定的顺序去访问共享资源
2. 在访问的其他锁的时候,需要先将字节的锁解开
3.trylock方式定义锁
-
互斥锁的使用以及注意事项以及互斥锁demo
2020-11-20 11:21:57使用mutex(互斥量、互斥锁)一般步骤: pthread_mutex_init 函数 初始化一个互斥锁(互斥量) —> 初值可看作1 int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr... -
线程同步 条件变量 互斥锁的使用
2018-11-13 11:33:48线程同步 条件变量 互斥锁的使用 -
Windows互斥锁的使用
2019-08-27 11:03:14首先是来看一下没使用互斥锁的情况 // InterlockedIncrementUse.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "InterlockedIncrementUse.h" using namespace std; ULONG g_count = 0; ... -
Linux——线程安全、互斥锁的使用
2020-11-20 16:01:17文章目录为什么会有线程安全问题互斥锁的引入互斥锁的使用函数接口例子:抢票系统死锁的概念 为什么会有线程安全问题 我们知道,多线程编程时,创建出来的线程对应同一个虚拟地址空间,即拥有相同的数据,假设多个... -
线程-互斥锁的使用
2020-07-18 17:24:22锁的使用过程:任务访问临界资源前申请锁,访问完释放锁 二、函数介绍 1.互斥锁的初始化 方法1:动态方式创建互斥锁 #include<pthread.h> int pthread_mutex_init(pthread_mutex_t *restrict mutex,const ... -
C++互斥锁的使用
2020-07-31 11:31:471.创建互斥锁 pthread_mutex_t m_nMutex; pthread_mutexattr_t sAttr; pthread_mutexattr_init(&sAttr); pthread_mutexattr_settype(&...互斥锁的类型:有以下几个取值空间: PTHREAD_MUTEX_TIMED_N -
Mysql 中互斥锁的使用
2012-04-09 11:35:00Mysql 中互斥锁的使用 本文介绍如在在多线程mysql代码开发中使用互斥锁。 mysql自己对c++的mutex又进行了一次封装,封装的代码可以在include/mysql/psi/mysql_thread.h 中找到。 下面大概地介绍下如何使用... -
mysql 互斥_Mysql 中互斥锁的使用
2021-01-19 03:45:44本文介绍如在在多线程mysql代码开发中使用互斥锁。mysql自己对c++的mutex又进行了一次封装,封装的代码可以在include/mysql/psi/mysql_thread.h 中找到。下面大概地介绍下如何使用互斥锁。锁的生命周期大体为: 初始... -
pthread_mutex_lock互斥锁的使用
2018-11-21 15:46:14//互斥锁的使用 #include&lt;errno.h&gt; #include&lt; cstring&gt; #include&lt; iostream&gt; #include&lt; cstdlib&gt; #include&... -
不同进程之间的互斥锁的使用
2013-01-21 23:40:01前段时间碰到个需求,关于Linux共享内存下的互斥锁的使用 我的设想是给读写进程共享的数据结构上添加上一个互斥锁 比如 typedef struct st_setting{ struct obsedata data; -
NDK你必须学习的技术,pthread线程同步互斥锁的使用
2018-01-04 02:21:112. NDK你必须学习的技术,pthread线程同步互斥锁的使用 3. NDK你必须学习的技术,pthread线程简单的生产者消费者模式 我们学习过pthread的线程创建后,再来学习线程同步互斥锁的使用,互斥锁类似于java线程的同步... -
RDA 互斥锁的使用
2017-11-15 11:23:00互斥锁提供一个可以在同一时间,只让一个线程访问临界资源的的操作接口。互斥锁(Mutex)是个提供线程同步的基本锁。上锁后,其他的线程如果想要锁上,那么会被阻塞,直到锁释放后。 如果,在锁释放后,有多个线程被... -
线程同步、条件变量、互斥锁的使用
2018-07-09 11:34:35线程同步、条件变量、互斥锁的使用https://blog.csdn.net/yusiguyuan/article/details/14161225 -
Linux C 互斥锁的使用
2019-06-13 14:45:22互斥锁的作用 保护共享数据: 在并发机制的情况下,有时候会有多个线程同时访问同一片数据,为了保护数据操作的准确性就需要通过加锁来进行保护。 保持操作互斥: 可能一个程序会有多个操作,但是同一个时间只能有... -
mysql mutex_Mysql 中互斥锁的使用
2021-01-19 05:17:39本文介绍如在在多线程mysql代码开发中使用互斥锁。mysql自己对c++的mutex又进行了一次封装,封装的代码可以在include/mysql/psi/mysql_thread.h 中找到。下面大概地介绍下如何使用互斥锁。锁的生命周期大体为: 初始... -
线程同步时互斥锁的使用注意事项
2019-09-26 13:37:16问题:线程互斥锁使用不当, 将同一互斥锁用于多处不同同步量,导致同一线程内同步变量时出现自锁 主要现象表现:界面假死,初步判断是线程互锁, 此时通常通过日志打印当前调用线程ID(windows平台... -
Swift之互斥锁的使用
2015-12-14 17:52:13oc中的互斥锁: @synchronized(self) { //需要执行的代码块 } swift中的互斥锁 objc_sync_enter(self) //需要执行的代码块 objc_sync_exit(self) 至于其他多线程的API和以前的一样,只是少了perform这一类... -
【博客302】Go的互斥锁的使用
2020-06-20 11:56:44内容: 当多个协程去操作同一数据块的时候,会产生...一、没有互斥锁的竞争例子: package main import ( "fmt" "runtime" "sync" ) var ( counter int wg sync.WaitGroup mutex sync.Mutex ) func main() {
-
基于Flink+Hudi构建企业亿级云上实时数据湖教程(PC、移动、小
-
基于Qt的LibVLC开发教程
-
Jsplumb从入门到实战
-
智能停车场云平台(附vue+SpringBoot前后端项目源码)
-
MySQL NDB Cluster 负载均衡和高可用集群
-
英特尔®Cyclone®10 LP设备家族引脚连接准则.docx
-
bro-2.6.4.tar.gz
-
二维数组中的查找
-
中断
-
统一的复杂性中心,可从PPI网络识别必需蛋白
-
【比特币价格】AAX行情速报—做好比特币可能会触达60000美金,再创历史新高的心理准备
-
自动化测试Python3+Selenium3+Unittest
-
videoClient.rar
-
Linux基础入门系列课程
-
Python启蒙到架构师的核心技术精讲课程
-
Effect of dichroic azo-dye doped on ferroelectric liquid crystals
-
js身份证号码带*号处理
-
一种半球形天空亮度测量仪器的研制
-
IASC-2P02:IASC 2P02中用于分配的个人存储库-源码
-
stlink:开源STM32 MCU编程工具集-源码