线程同步(互斥锁)

参考:

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

C++ 在类里面使用多线程技术

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;
}

猜你喜欢

转载自blog.csdn.net/BJUT_bluecat/article/details/84342851