参考:
https://blog.csdn.net/google19890102/article/details/62047798
https://blog.csdn.net/fengbingchun/article/details/73521630 c++11中的mutex
当多个控制线程共享相同内存的时候,要确保线程看到一致的数据视图,如果其中一个线程使用的变量不会被其他的线程修改或者使用,就还好,否则要注意线程的同步问题。一般线程的同步问题通过互斥量或者条件变量来解决。
互斥锁解决线程同步
用来锁定对共享资源的访问,对线程来说,整个地址空间都是共享的资源。
1.如果一个线程锁定了一个互斥锁,则没有其他线程可以锁定这个互斥锁。
2.如果已经有了线程锁定了一个互斥锁,然后有另一个线程想去锁定他,那么这个线程会被挂起,直到第1个线程解除锁定,第二个会被唤醒并且继续执行,同时锁定这个互斥锁。
互斥锁是通过锁的机制来实现线程间的同步问题。互斥锁的基本流程为:
初始化一个互斥锁: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的错误码。
同时,解锁的过程中,也需要满足两个条件:
解锁前,互斥锁必须处于锁定状态;
必须由加锁的线程进行解锁。
当互斥锁使用完成后,必须进行清除。
通过互斥锁完成线程同步,其中还发现一些问题,其中我是先把线程函数写到类里面,发现会报错。发现线程创建函数的参数是非成员函数,线程函数要设置成static类的,static的静态函数里面访问的成员也必须是static的,但是Xcode里面还有莫名其妙的问题,我就直接面向过程了。
C++之static及其作用域https://blog.csdn.net/mary19920410/article/details/69053361
https://www.cnblogs.com/lifan3a/articles/7644871.html
https://blog.csdn.net/wei_sj/article/details/80770439
互斥锁非面向对象
每个线程使用x时候加锁,等开锁之后另一个才能处理x。
//
// main.cpp
// 互斥锁非面向对象
//
// Created by 蓝猫 on 2018/11/23.
// Copyright © 2018年 蓝猫. All rights reserved.
//
//
#include <iostream>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <memory>
#include <mutex>
using namespace std;
int x;//全局变量
pthread_mutex_t mutex1;//定义一个互斥量 c++11有了mutex 不能取这个名字
void *threaddeal1(void *arg)
{
while (x>0) {
pthread_mutex_lock(&mutex1);//加锁
printf("线程1正在运行:x=%d\n",x);
x--;
pthread_mutex_unlock(&mutex1);//开锁
sleep(1);
}
pthread_exit(NULL);
}
void *threaddeal2(void *arg)
{
while (x>0) {
pthread_mutex_lock(&mutex1);//加锁
printf("线程2正在运行:x=%d\n",x);
x--;
pthread_mutex_unlock(&mutex1);//开锁
sleep(1);
}
pthread_exit(NULL);
}
void Main()
{
pthread_t thread1;//线程1
pthread_t thread2;//线程2
x=10;
int ret;
ret=pthread_mutex_init(&mutex1, NULL);
if(ret!=0)
{
cout<<"互斥锁初始化失败"<<endl;
exit(1);
}
ret=pthread_create(&thread1, NULL, threaddeal1, NULL);
//创建线程的第三个参数是非成员变量型的 要把它改成static 不然会报上面的错误
if(ret!=0)
{
cout<<"创建线程1失败"<<endl;
exit(1);
}
ret=pthread_create(&thread2, NULL, threaddeal2, NULL);
if(ret!=0)
{
cout<<"创建线程2失败"<<endl;
exit(1);
}
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
}
int main(int argc, const char * argv[])
{
Main();
return 0;
}
将互斥锁代码注释
//
// main.cpp
// 互斥锁非面向对象
//
// Created by 蓝猫 on 2018/11/23.
// Copyright © 2018年 蓝猫. All rights reserved.
//
//
#include <iostream>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <memory>
#include <mutex>
using namespace std;
int x;//全局变量
pthread_mutex_t mutex1;//定义一个互斥量 c++11有了mutex 不能取这个名字
void *threaddeal1(void *arg)
{
while (x>0) {
//pthread_mutex_lock(&mutex1);//加锁
printf("线程1正在运行:x=%d\n",x);
x--;
//pthread_mutex_unlock(&mutex1);//开锁
sleep(1);
}
pthread_exit(NULL);
}
void *threaddeal2(void *arg)
{
while (x>0) {
//pthread_mutex_lock(&mutex1);//加锁
printf("线程2正在运行:x=%d\n",x);
x--;
//pthread_mutex_unlock(&mutex1);//开锁
sleep(1);
}
pthread_exit(NULL);
}
void Main()
{
pthread_t thread1;//线程1
pthread_t thread2;//线程2
x=10;
int ret;
ret=pthread_mutex_init(&mutex1, NULL);
if(ret!=0)
{
cout<<"互斥锁初始化失败"<<endl;
exit(1);
}
ret=pthread_create(&thread1, NULL, threaddeal1, NULL);
//创建线程的第三个参数是非成员变量型的 要把它改成static 不然会报上面的错误
if(ret!=0)
{
cout<<"创建线程1失败"<<endl;
exit(1);
}
ret=pthread_create(&thread2, NULL, threaddeal2, NULL);
if(ret!=0)
{
cout<<"创建线程2失败"<<endl;
exit(1);
}
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
}
int main(int argc, const char * argv[])
{
Main();
return 0;
}
出错的代码
//
// main.cpp
// 互斥锁解决线程同步
//
// Created by 蓝猫 on 2018/11/22.
// Copyright © 2018年 蓝猫. All rights reserved.
//
#include <iostream>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <memory>
using namespace std;
void *threaddeal(void *arg)
{
pthread_exit(NULL);
}
class Mutex
{
private:
static int x;//全局变量
static pthread_mutex_t mutex1;//定义一个互斥量 mutex是c++11里面的
pthread_t thread1;//线程1
pthread_t thread2;//线程2
public:
Mutex();
static void *threaddeal1(void *arg);//不写成静态成员函数会报错
//reference to non-static member function must be called
static void *threaddeal2(void *arg);//
void Main();
};
Mutex::Mutex()
{
x=10;
int ret;
ret=pthread_mutex_init(&mutex1, NULL);
if(ret!=0)
{
cout<<"互斥锁初始化失败"<<endl;
exit(1);
}
}
void *Mutex::threaddeal1(void *arg)
{
while (x>0) {
pthread_mutex_lock(&mutex1);//加锁
printf("线程1正在运行:x=%d\n",x);
x--;
pthread_mutex_unlock(&mutex1);//开锁
sleep(1);
}
pthread_exit(NULL);
}
void *Mutex::threaddeal2(void *arg)
{
while (x>0) {
pthread_mutex_lock(&mutex1);//加锁
printf("线程2正在运行:x=%d\n",x);
x--;
pthread_mutex_unlock(&mutex1);//开锁
sleep(1);
}
pthread_exit(NULL);
}
void Mutex::Main()
{
int ret;
ret=pthread_create(&thread1, NULL, threaddeal1, NULL);
//创建线程的第三个参数是非成员变量型的 要把它改成static 不然会报上面的错误
if(ret!=0)
{
cout<<"创建线程1失败"<<endl;
exit(1);
}
ret=pthread_create(&thread2, NULL, threaddeal2, NULL);
if(ret!=0)
{
cout<<"创建线程2失败"<<endl;
exit(1);
}
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
}
int main(int argc, const char * argv[])
{
shared_ptr<Mutex> obj=make_shared<Mutex>();
obj->Main();
return 0;
}