Linux - 线程同步

No.1 线程同步

一、互斥量:互相之间排斥

mutex
1. 初始化				pthread_mutex_init				
2. 上锁					pthread_mutex_lock			//加锁,如果已经枷锁则会阻塞
3. 判断是否上锁	pthread_mutex_trylock		//lock的非阻塞版,未加锁返回0
4. 解锁					pthread_mutex_unlock		//解锁
5. 销毁锁				pthread_mutex_destroy
int pthread_mutex_init(
	pthread_mutex_t *restrict mutex,	//初始化
	const pthread_mutexattr *restrict attr); //标志,状态
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//可以直接赋值初始化
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mute);

整体很合理,但是过程很不合理,f1或者f2长时间执行后才会轮到另外的一个线程。并且是阻塞的。

二、条件变量:一般互斥量和条件变量一起使用。

条件变量:

	cond
1. 初始化								pthread_cond_init
2. 条件变量等待							pthread_cond_wait
3. 发信号给条件变量 解除等待				pthread_cond_wait
int pthread_cond_init(
	pthread_cond_t *restrict cond,	//初始化
	const pthread_condattr *restrict attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

cond也有临界数据脏的问题,因此要上锁。
在这里插入图片描述
在这里插入图片描述
cond与mutex结合使用:

 		#include <stdio.h>
#include <pthread.h> 
#include <unistd.h>     //sleep
pthread_cond_t cond; //定义条件变量
pthread_mutex_t mutex;
int  n = 0;
int m = 50000000;
void* f1()
{
    for(int i=0;i<m;i++)
    {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond,&mutex);//阻塞式等待
        n++;
        //printf("线程一==========%d\n",n);
        printf("%d\n",n);
        pthread_mutex_unlock(&mutex);
    } 
}
void* f2()
{
    for(int i=0;i<m;i++)
    {
        pthread_cond_wait(&cond,&mutex);//阻塞式等待
        
        printf("线程二++++++%d\n",n);
    } 
}
int main()
{
    pthread_t p1,p2;
    //初始化互斥量
    pthread_cond_init(&cond,NULL);
    pthread_mutex_init(&mutex,NULL);
    pthread_create(&p1,NULL,f1,NULL);
    pthread_create(&p2,NULL,f1,NULL);
    for(int i=0;i<m*2;i++)
    {
        pthread_cond_signal(&cond);
    }

    pthread_join(p1,NULL);
    pthread_join(p2,NULL);
    pthread_cond_destroy(&cond);
    pthread_mutex_destroy(&mutex);
    printf("n:%d,m:%d\n",n,m*2);
    return 0;
}

三、读写锁

读锁 	写锁
读读		相容:一个线程在读的时候,其他线程也可以读
写写、读写		相斥:某个线程在写的时候,其他线程不能操作
			pthread_rwlock_t
		1. 初始书				pthread_rwlock_init
		2. 获取					pthread_rwlock_wrlock	pthread_rwlock_rdlock
		3. 释放					pthread_rwlock_unlock
		4. 销毁					pthread_rwlock_destroy

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <stdio.h>
#include <pthread.h> 
#include <unistd.h>     //sleep
pthread_rwlock_t rwlock; //定义读写锁
int  n = 0;
int m = 50000000;
void* read_()
{
    for(int i=0;i<m;i++)
    {
        pthread_rwlock_rdlock(&rwlock);
        printf("读操作==============\n");
        pthread_rwlock_unlock(&rwlock);
    } 
}
void* write_()
{
    for(int i=0;i<m;i++)
    {
       pthread_rwlock_wrlock(&rwlock);
        printf("写操作-----------\n");
        pthread_rwlock_unlock(&rwlock);
    } 
}
void* read2()
{
    for(int i=0;i<m;i++)
    {
       pthread_rwlock_rdlock(&rwlock);
        printf("读操作++++++++++\n");
        pthread_rwlock_unlock(&rwlock);
    } 
}

int main()
{
    pthread_t p1,p2;
    //初始化读写锁
    pthread_rwlock_init(&rwlock,NULL);
    pthread_create(&p1,NULL,read_,NULL);
    pthread_create(&p2,NULL,read2,NULL);
    pthread_join(p1,NULL);
    pthread_join(p2,NULL);
    printf("n:%d,m:%d\n",n,m*2);
    printf("rwlock : %d\n",rwlock);
    int ret = pthread_rwlock_destroy(&rwlock);
    printf("des:%d\n",ret);
    return 0;
}

它跟互斥锁有同样的问题,但是他影响不打,没有关系
读写锁和互斥锁是一样的:
都是上锁后排斥其他锁,本身有锁的前提下可以通过trylock来提前返回
但是本质上面还是要等 还是阻塞的。

四、自旋锁

一直循环检查锁是否可用,如果不可用那就继续循环,如果可用,那就用。
	pthread_spinlock_t
	1. 初始化		pthread_spin_init
	2. 获取			pthread_spin_lock
	3. 解锁			pthread_spin_unlock
	4. 销毁			pthread_spin_destroy

五、选择方法

  • 自旋锁建立锁的小号比较小,但是当线程阻塞的时候,一直循环的消耗比较大。所以当阻塞情况比较多的时候,不建议使用。
  • 互斥锁建立的消耗比较大,但当线程阻塞的时候,它阻塞所以无消耗,所以当阻塞时间比较多,索锁的数量比较少的时候,使用互斥锁比较划得来。

首先看锁的数量,其次看阻塞是否比较多。

例如:
10个线程 加锁线程比较少,使用自旋锁
两个线程 枷锁线程比较长,使用互斥锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值