C/C++锁使用总结

目录

概述

C互斥锁

C条件锁 

C读写锁


概述

        在多线程并发且存在改写和访问公共数据的情况下,需要保证改写和访问数据对象是准确的,同一时间内只能有一个线程进行对公共数据的改写,保证数据的写正确,同时在改写数据同时,不能访问数据,保证数据的读正确。锁为了公共数据的操作提供了安全的保护机制。C/C++语言有互斥锁、条件锁、递归锁、自旋锁、读写锁,以下我们从锁的使用流程和使用示例逐一展开讲解。

C互斥锁

头文件

        #include <pthread.h>

数据类型

        pthread_mutex_t 

声明

        pthread_mutex_t g_mutex;

初始化

        1、动态初始化       

        pthread_mutex_init(&lock, NULL);  // 成功返回0,失败返回非0

        2、静态初始化

        1)pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; 

加锁

        // 普通加锁,重复加锁会阻塞进程

        int pthread_mutex_lock (pthread_mutex_t *__mutex);

        // 重复加锁不阻塞进程 

        int pthread_mutex_trylock (pthread_mutex_t *__mutex);

        // 带有超时功能加锁
        int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abs_timeout);

解锁

        int pthread_mutex_unlock (pthread_mutex_t *__mutex);

去初始化

        int pthread_mutex_destroy(pthread_mutex_t *mutex);

示例

#include <pthread.h>
#include <stdio.h>


pthread_mutex_t g_mutex;

int g_data = 0;
int do_num = 10;

void* thread1_func(void* data)
{
        int i = 0;
        for (i = 0; i < 10; i++){
                pthread_mutex_lock(&g_mutex);
                printf("thread1_func g_data:%d\n", g_data);
                g_data++;
                pthread_mutex_unlock(&g_mutex);
        }

        return NULL;
}

void* thread2_func(void* data)
{
        int i = 0;
        for (i = 0; i < 10; i++){
                pthread_mutex_lock(&g_mutex);
                printf("thread2_func g_data:%d\n", g_data);
                g_data--;
                pthread_mutex_unlock(&g_mutex);
        }
        return NULL;
}


       

int main(int argc, char* argv[])
{
        // 初始化
        pthread_mutex_init(&g_mutex, NULL);

        // 创建2个线程
        pthread_t thread1;
        pthread_t thread2;

        pthread_create(&thread1, NULL, thread1_func, NULL);
        pthread_create(&thread2, NULL, thread2_func, NULL);

        // 等待线程退出
        pthread_join(thread1, NULL);
        pthread_join(thread2, NULL);

        // 去初始化
        pthread_mutex_destroy(&g_mutex);

        printf("test done \n");
        return 0;

}

   

C条件锁 

       条件锁是条件变量结合普通互斥锁实现等待和唤醒的一个机制,主要应用场景为生产者和消费者对资源操作的应用。

头文件

        #include <pthread.h>

数据类型

        // 互斥锁数据类型

        pthread_mutex_t 

        // 条件变量数据类型

        pthread_cond_t

声明

        pthread_mutex_t g_mutex;

        pthread_cond_t g_condition;

初始化

        pthread_mutex_init(&g_mutex, NULL);

        pthread_cond_init(&g_condition, NULL);

条件锁等待

        pthread_mutex_lock(&g_mutex);

        // 等待唤醒前解锁,唤醒线程会上锁,然后在解锁

        pthread_cond_wait(&g_condition, &g_mutex);

        pthread_mutex_unlock(&g_mutex);

条件锁唤醒

        pthread_cond_broadcast(&g_condition);

条件锁销毁

        // 销毁互斥锁

        pthread_mutex_destroy(&g_mutex);

        // 销毁条件变量

        pthread_cond_destroy(&g_condition);

示例

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

// 生产者条件锁声明
pthread_mutex_t g_productLock;
pthread_cond_t g_productCondition;

// 消费者条件锁声明
pthread_mutex_t g_consumerLock;
pthread_cond_t g_consumerCondition;


// 定时线程回调函数类型
// typedef void* (ThreadCallback*)(void* data)

// 消息定义
int g_msgs = 0;
int g_msgsNum = 10;
pthread_mutex_t g_msgLock;

static int GetMsgs()
{
	int msg = 0;
	pthread_mutex_lock(&g_msgLock);
	msg = g_msgs;
	pthread_mutex_unlock(&g_msgLock);
	return msg;
}

static void ProductMsg()
{
	printf("Product msgs:%d\n", g_msgs);
	pthread_mutex_lock(&g_msgLock);
	g_msgs++;
	pthread_mutex_unlock(&g_msgLock);

}

static void ConsumeMsg()
{
	printf("consume msgs:%d\n", g_msgs);
	pthread_mutex_lock(&g_msgLock);
	g_msgs--;
	pthread_mutex_unlock(&g_msgLock);

}

// 消息生成线程
static void* ProductMsgThread(void* data)
{
	int i = 0;
	int msgs = GetMsgs();
	for (i = 0; i < g_msgsNum; i++){
	        // 有消息时,不生产,等待唤醒
        	msgs = GetMsgs();	
		if (msgs > 0){
                	pthread_mutex_lock(&g_consumerLock);
			// 唤醒消费者进行消费
			pthread_cond_broadcast(&g_consumerCondition);
			pthread_cond_wait(&g_productCondition, &g_consumerLock);
			pthread_mutex_unlock(&g_consumerLock);
				
        	} else {
			ProductMsg();

        	}	
		sleep(1);

	}
	pthread_cond_broadcast(&g_consumerCondition);
	printf("ProductMsgThread end \n");

}

// 消息消费线程
static void* ConsumeMsgThread(void* data)
{
        int i = 0;
        int msgs = GetMsgs();
        for (i = 0; i < g_msgsNum; i++){
                // 有消息时,不生产,等待唤醒
		msgs = GetMsgs();
                if (msgs == 0){
                        pthread_mutex_lock(&g_productLock);
                        // 唤醒消费者进行消费
                        pthread_cond_broadcast(&g_productCondition);
			pthread_cond_wait(&g_consumerCondition, &g_productLock);
                        pthread_mutex_unlock(&g_productLock);

                } else {
                        ConsumeMsg();

                }
                sleep(1);

        }
	g_msgs = 0;
	pthread_cond_broadcast(&g_productCondition);
	printf("ConsumeMsgThread end i:%d\n", i);
}


int main(int argc, char*argv[])
{
	//初始化条件锁
	pthread_mutex_init(&g_productLock, NULL);
	pthread_mutex_init(&g_consumerLock, NULL);
	pthread_cond_init(&g_productCondition, NULL);
	pthread_cond_init(&g_consumerCondition, NULL);


	// 消息生产者和消息消费者创建
	pthread_t productThread;
	pthread_t consumeThread;
	pthread_create(&productThread, NULL, ProductMsgThread, NULL);
	pthread_create(&consumeThread, NULL, ConsumeMsgThread, NULL);


	// 等待生产和消费 
	sleep(10);

	// 条件锁销毁
	pthread_mutex_destroy(&g_productLock);
	pthread_mutex_destroy(&g_consumerLock);
	pthread_cond_destroy(&g_productCondition);
	pthread_cond_destroy(&g_consumerCondition);


	// 等待线程退出
	pthread_join(productThread, NULL);
	pthread_join(consumeThread, NULL);

	printf("test end\n");

	return 0;
}

C读写锁

使用场景

        读共享数据次数比写共享的次数多,

头文件

        #include <pthread.h>

数据类型

        pthread_rwlock_t;

声明

        pthread_rwlock_t g_rwlock;

初始化

        pthread_rwlock_init(&g_rwlock, NULL);

读写加锁

        // 读加锁

        pthread_rwlock_rdlock(&g_rwlock);

        // 写加锁

        pthread_rwlock_wrlock(&g_rwlock);

读写解锁

        pthread_rwlock_unlock(&g_rwlock);

读写锁销毁

        pthread_rwlock_destroy(&g_rwlock);

示例

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

// 读写锁声明
pthread_rwlock_t g_rwlock;

// 全局共享数据
int g_data = 0;

// 读写数据操作次数
int g_rwNum = 10;

static void* WriteThread(void* data)
{
	int i = 0;
	for (i = 0; i < g_rwNum; i++){
		pthread_rwlock_wrlock(&g_rwlock);
		g_data++;
		printf("WriteThread g_data:%d\n", g_data);
		pthread_rwlock_unlock(&g_rwlock);
		int a = rand()%5;
		usleep(a);
	}

}

static void* ReadThread1(void* data)
{
        int i = 0;
        for (i = 0; i < g_rwNum; i++){
                pthread_rwlock_rdlock(&g_rwlock);
                printf("ReadThread1 g_data:%d\n", g_data);
                pthread_rwlock_unlock(&g_rwlock);
		int b = rand()%5;
		usleep(b);
        }

}

static void* ReadThread2(void* data)
{
        int i = 0;
        for (i = 0; i < g_rwNum; i++){
                pthread_rwlock_rdlock(&g_rwlock);
                printf("ReadThread2 g_data:%d\n", g_data);
                pthread_rwlock_unlock(&g_rwlock);
		int c = rand()%5;
		usleep(c);
        }

}

int main(int argc, char* argv[])
{
	// 读写锁初始化
	pthread_rwlock_init(&g_rwlock, NULL);

	// 创建写线程
	pthread_t writeThreadId;
	pthread_create(&writeThreadId, NULL, WriteThread, NULL);

	// 创建读线程1
	pthread_t readThreadId1;
	pthread_create(&readThreadId1, NULL, ReadThread1, NULL);	

	// 创建读线程2
	pthread_t readThreadId2;
	pthread_create(&readThreadId2, NULL, ReadThread2, NULL);


	// 等待线程退出
	pthread_join(writeThreadId, NULL);
	pthread_join(readThreadId1, NULL);
	pthread_join(readThreadId2, NULL);

	// 读写锁的销毁
	pthread_rwlock_destroy(&g_rwlock);
	printf("test end \n");

}



  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值