多线程学习笔记3

6 篇文章 0 订阅
6 篇文章 7 订阅
std::lock()

一次锁住>=2个互斥量 (谨慎使用)

它不存在因为多个线程因为锁的顺序而导致的死锁风险

只有同时锁住才会继续向下执行(要么都锁住,要么都不锁)

std::lock(my_mutex1,my_mutex2,..);
my_mutex1.unlock();//解锁还是要继续写
my_mutex2.unlock();
std::adopt_lock

在用这个参数前,我们一定要记得先lock

std::lock()std::lock_guard结合使用

有了std::adopt_lock std::lock_guard就在构造时就不lock了,析构正常unlock

std::lock(my_mutex1,my_mutex2);
std::lock_guard<std::mutex> a_guard(my_mutex1,std::adopt_lock);
std::lock_guard<std::mutex> b_guard(my_mutex2,std::adopt_lock);
std::unique_lock

unique_lock是一个类模板 , 可以完全取代lock_guard , 但一般用lock_guard(推荐使用)

unique_locklock_guard灵活一点, 效率上差一点 , 内存多一点

std::unique_lock<std::mutex> myguard(my_mutex);
std::unique_lock<std::mutex> myguard(my_mutex,std::adopt_lock);//std::adopt_lock放在第二个,表示这个互斥量已经被lock了
std::try_to_lock

我们尝试用lock()去这个mutex , 如果没有锁成功 , 就执行没锁成功的代码 , 然后再执行后续代码

使用前提 : 这个线程不能自己先lock

int command=0;

class A{
public:
	void inmRQ(){
		for(int i=1;i<=100000000;i++){
			my_mutex1.lock();
			mRQ.push(i);
			my_mutex1.unlock();
			cout<<"start"<<endl;
			
		}
	}
	int outmRQtem(){
		std::unique_lock<std::mutex> myguard(my_mutex1,std::try_to_lock);
		if(myguard.owns_lock()){//拿到锁了
			if( !mRQ.empty() ){
				command=mRQ.front();
				mRQ.pop();
			}
		}else{//没拿到锁
			cout<<"I have no lock"<<endl;
		}
		return command;
	}

	void outmRQ(){
		command=0;
		for(int i=1;i<=100000000;i++){
			command=outmRQtem();
			cout<<command<<endl;
		}
		cout<<"end"<<endl;
	}
private:
	std::queue<int> mRQ;
	std::mutex my_mutex1;
};

int main(){
	A a;
	
	thread myout(&A::outmRQ,ref(a));
	thread myin(&A::inmRQ,ref(a));

	myin.join();
	myout.join();
	return 0;
}
std::defer_lock

使用前提 : 不能自己先lock,否者会报异常

初始化一个没有加锁的mutex

std::unique_lock<std::mutex> myguard(my_mutex1,std::defer_lock);//将my_mutex1与myguard绑定到一起
myguard.lock();//这样就可以自己亲自加锁
myguard.unlock();//也可以自己亲自解锁,如果不写也会可以生命周期调用析构函数自动解锁
try_lock()

尝试给互斥量加锁 , 如果拿不到锁 , 则返回false , 如果拿到锁了 , 就返回true , 这个函数不会阻塞

一般和std::defer_lock搭配使用

	std::unique_lock<std::mutex> myguard(my_mutex1,std::defer_lock);
    if(myguard.try_lock()){//拿到锁了
        if( !mRQ.empty() ){
            command=mRQ.front();
            mRQ.pop();
        }
    }else{//没拿到锁
        cout<<"I have no lock"<<endl;
    }
release()

返回它所管理的mutex对象指针 , 并释放所有权 即unique_lockmutex不再有关系

如果原来的mutex对象处于加锁状态 , 你有责任接管过来并负责解锁

    std::unique_lock<std::mutex> myguard(my_mutex1);

    if( !mRQ.empty() ){
        command=mRQ.front();
        mRQ.pop();
    }
    std::mutex *p=myguard.release();
    p->unlock();
    //my_mutex1.unlock();//release之后也可以这样用
unique_lock所有权的传递

方法一

std::unique_lock<std::mutex> myguard1(my_mutex1);//myguard1拥有my_mutex1的所有权
//这个所有权可以转移但不能复制,类似于智能指针
std::unique_lock<std::mutex> myguard2(std::move(myguard1));//移动所有权,与myguard2绑到一起,myguard1指向空

方法二

class A{
public:
	std::unique_lock<std::mutex> my_move(){
		std::unique_lock<std::mutex> tem(my_mutex1);
		return tem;
	}
	void inmRQ(){
		for(int i=1;i<=100000000;i++){
			my_mutex1.lock();
			mRQ.push(i);
			my_mutex1.unlock();
			cout<<"start"<<endl;
		}
	}
	int outmRQtem(){
		std::unique_lock<std::mutex> myguard=my_move();
		if( !mRQ.empty() ){
			command=mRQ.front();
			mRQ.pop();
		}
		return command;
	}

	void outmRQ(){
		command=0;
		for(int i=1;i<=100000000;i++){
			command=outmRQtem();
			cout<<command<<endl;
		}
		cout<<"end"<<endl;
	}
private:
	std::queue<int> mRQ;
	std::mutex my_mutex1;
};
粒度

有人把锁头锁住的代码多少称为粒度

锁住代码少 , 粒度细 ,效率高 , 反之多 ,效率低

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值