pthread_mutex 应用

本文详细介绍了pthread互斥锁的使用方法,包括初始化、销毁、上锁与解锁等操作,并通过示例代码展示了如何正确使用互斥锁来保护共享资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、 pthread_mutex 家庭成员:

1.int pthread_mutex_init (pthread_mutex_t *mutex , pthread_mutexattr_t * attr );

Description

The pthread_mutex_init function initializes the given mutex with the given attributes. Ifattr is null, then the default attributes are used.


2. int pthread_mutex_destroy (pthread_mutex_t *mutex );

Description

The pthread_mutex_destroy function destroys the given mutex. If the mutex is already destroyed, thenerrno is set to EINVAL. If the mutex is locked, then errno is set to EBUSY.


3.int pthread_mutex_lock (pthread_mutex_t *mutex );

Description

The pthread_mutex_lock function locks the given mutex. If the mutex is already locked, then the calling thread blocks until the thread that currently holds the mutex unlocks it.


4.int pthread_mutex_trylock (pthread_mutex_t *mutex );

Description

The pthread_mutex_trylock function tries to lock the given mutex. If the mutex is already locked, the function returns without waiting for the mutex to be unlocked.

Returns

The pthread_mutex_trylock function returns zero if the call is successful, otherwise it setserrno to EINVAL and returns -1.


5.int pthread_mutex_unlock (pthread_mutex_t *mutex );

Description

The pthread_mutex_unlock function unlocks the given mutex.


二、成员作用

1.  互斥锁的初始化和销毁

.初始化有两种初始化方式:

a.   对于静态分配的互斥锁一半用宏赋值的方式初始化

eg:static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;


b.   对于动态分配的互斥锁(如调用malloc)或分配在共享内存中,则必须调用

pthread_mutex_init(pthread_mutex*mutex, pthread_mutexattr_t *mutexattr)函数来进行初始化。

动态分配释放例子:
pthread_mutex_init(*mutex ,*attr);
pthread_mutex_destory(*mutex)
pthread_mutexattr_init(*attr)
pthread_mutexattr_destory(*attr)动态分配的代码:
pthread_mutex_t
*lock;
lock=(pthread_mutex_t *)malloc(sizeof(szieof(pthread_mutex_t)));
pthread_mutex_init(lock ,NULL);

. 互斥锁摧毁
pthread_mutex_destory(lock);
free(lock);

销毁一个互斥锁即意味着释放它所占用的资源,且要求锁当前处于开放状态。由于在Linux中,互斥锁并不占用任何资源,因此LinuxThreads中的 pthread_mutex_destroy()除了检查锁状态以外(锁定状态则返回EBUSY)没有其他动作。

2.  互斥锁上锁、尝试上锁和解锁

        要对公共变量进行上锁来进行保护,必须最少要上两个锁以上,换句话说就得调用pthread_mutex_lock()函数两次以上,否则,只是上一个锁会达不到相应的效果。尝试上锁pthread_mutex_trylock()和pthread_mutex_lock()的区别是:后者会阻塞等待另外一个锁被解锁;前者尝试去加锁,如果不成功就返回非0,如果成功返回0,不会产生阻塞。

       每次上锁之后,一定要解锁,否则会造成程序一直在阻塞状态。


三、代码讲解:

代码说明1:互斥锁基本应用

#include<stdio.h>

#include<pthread.h>

#include"unistd.h"

pthread_mutex_tmutex = PTHREAD_MUTEX_INITIALIZER;

intcount = 0;

void*consume( void *arg)

{

while(1 )

{

pthread_mutex_lock(&mutex );

printf("************************consumebegin lock\n");

printf("************************consumed%d\n",count );

sleep(2);

count++;

printf("************************consumed%d\n",count);

printf("************************consumeover lock\n");

pthread_mutex_unlock(&mutex );

printf("************************I'mout of pthread_mutex\n");

sleep(1);

}

}

void* produce( void * arg )

{

while(1 )

{

pthread_mutex_lock(&mutex );

printf("productbegin lock\n");

printf("Produced %d\n", count );

printf("productover lock\n");

pthread_mutex_unlock(&mutex );

printf("I'mout of pthread_mutex\n");

sleep(1);

}

}

intmain( void )

{

pthread_tthread1,thread2;

pthread_create(&thread1, NULL, &produce, NULL );

pthread_create(&thread2, NULL, &consume, NULL );

pthread_join(thread1,NULL);

pthread_join(thread2,NULL);

return0;

}



结果显示:

[elbort@elborttest1]$ gcc -Wall -lpthread -o test test.c

[elbort@elborttest1]$ ./test

productbegin lock

Produced0

productover lock

I'mout of pthread_mutex

************************consumebegin lock

************************consumed0

/*中间等待了2秒但是product线程没有执行|*/

************************consumed1

************************consumeover lock

************************I'mout of pthread_mutex

productbegin lock

Produced1

productover lock

I'mout of pthread_mutex

************************consumebegin lock

************************consumed1

************************consumed2

************************consumeover lock

************************I'mout of pthread_mutex

productbegin lock

Produced2

productover lock

I'mout of pthread_mutex


/************************************************************************/


代码说明2:单一调用互斥锁没效果

void*consume( void *arg)

{

while(1 )

{

pthread_mutex_lock(&mutex );

printf("************************consumebegin lock\n");

printf("************************consumed%d\n",count );

sleep(2);

count++;

printf("************************consumed%d\n",count);

printf("************************consumeover lock\n");

pthread_mutex_unlock(&mutex );

printf("************************I'mout of pthread_mutex\n");

sleep(1);

}

}

void* produce( void * arg )

{

while(1 )

{

count=count+5;

printf("Produced %d\n", count );

sleep(1);

}

}

intmain( void )

{

pthread_tthread1,thread2;

pthread_create(&thread1, NULL, &produce, NULL );

pthread_create(&thread2, NULL, &consume, NULL );

pthread_join(thread1,NULL);

pthread_join(thread2,NULL);

return0;

}

~

~

结果说明:

[elbort@elborttest1]$ ./test

Produced5

************************consumebegin lock

************************consumed5

Produced10 //线程comsume被中断,conut的值被线程product修改

************************consumed11

************************consumeover lock

************************I'mout of pthread_mutex




/********************************************************/

代码说明3pthread_mutex_trylock作用

intcount = 0;

void*consume( void *arg)

{

while(1 )

{

pthread_mutex_lock(&mutex );

printf("************************consumebegin lock\n");

printf("************************consumed%d\n",count );

sleep(2);

count++;

printf("************************consumed%d\n",count);

printf("************************consumeover lock\n");

pthread_mutex_unlock(&mutex );

printf("************************I'mout of pthread_mutex\n");

sleep(1);

}

}

void* produce( void * arg )

{

while(1 )

{

if(pthread_mutex_trylock(&mutex ) == 0)

{

printf("productbegin lock\n");

count++;

printf("Produced %d\n", count );

printf("productover lock\n");

pthread_mutex_unlock(&mutex );

printf("I'mout of pthread_mutex\n");

sleep(1);

}

else

{

printf("Ihave try!But i can lock the mutex!\n");

sleep(1);

}

}

}

intmain( void )

{

pthread_tthread1,thread2;

pthread_create(&thread1, NULL, &produce, NULL );

pthread_create(&thread2, NULL, &consume, NULL );

pthread_join(thread1,NULL);

pthread_join(thread2,NULL);

return0;

}


结果显示:

[elbort@elborttest1]$ ./test

************************consumebegin lock

************************consumed0

Ihave try!But i can lock the mutex!

Ihave try!But i can lock the mutex!

************************consumed1

************************consumeover lock

************************I'mout of pthread_mutex

productbegin lock

Produced2

productover lock

I'mout of pthread_mutex

************************consumebegin lock

************************consumed2

Ihave try!But i can lock the mutex!

Ihave try!But i can lock the mutex!

************************consumed3

************************consumeover lock

************************I'mout of pthread_mutex

productbegin lock

Produced4

productover lock

I'mout of pthread_mutex


<think>嗯,用户想要找关于pthread_mutex的练习题或示例代码。首先,我得回忆一下pthread库中互斥锁的基本用法和相关函数。用户可能对多线程编程中的同步机制不太熟悉,需要一些基础的例子来理解如何正确使用互斥锁。 首先,我应该提供一个简单的示例,展示如何用pthread_mutex_init初始化互斥锁,以及如何在多个线程中加锁和解锁。比如,一个全局变量被多个线程修改的情况,这时候不加锁会导致数据竞争,结果不正确。通过示例演示正确使用互斥锁后的效果。 然后,用户可能需要更复杂的例子,比如生产者-消费者问题。这时候需要用到互斥锁配合条件变量,这样能展示锁在同步中的实际应用。需要确保示例代码结构清晰,注释详细,方便用户理解。 接下来是练习题部分。题目应该由浅入深,从基本的使用到更复杂的问题。比如,第一个题目可以是简单的多线程累加,不使用锁会出现问题,使用锁后解决。第二个题目可以涉及死锁,让用户思考如何避免。第三个题目可能涉及读者写者问题,这样结合互斥锁和读写锁,扩展用户的知识。 同时,要确保代码示例中的错误检查,比如初始化互斥锁是否成功,加锁和解锁的返回值处理。虽然在实际练习中可能忽略错误处理,但良好的习惯需要培养,所以代码中加入错误检查会更好。 另外,用户提供的引用中有提到pthread_joinpthread_detach,可能在示例代码中创建线程后需要使用pthread_join来等待线程结束,避免主线程提前退出。这点需要注意,确保示例的正确运行。 还需要考虑不同平台下pthread库的支持,比如在Linux下编译需要链接-pthread选项,这点在代码注释中提醒用户,避免编译错误。 最后,总结部分要强调互斥锁的重要性,并建议用户通过实际调试来观察锁的行为,比如注释掉加锁部分后观察结果差异,这样能加深理解。</think>### pthread_mutex 基础示例与练习 #### 基础示例1:全局变量保护 ```c #include <stdio.h> #include <pthread.h> #define THREAD_NUM 5 int counter = 0; pthread_mutex_t mutex; void* thread_func(void* arg) { pthread_mutex_lock(&mutex); // 加锁 for (int i=0; i<10000; i++) { counter++; // 临界区操作 } pthread_mutex_unlock(&mutex); // 解锁 return NULL; } int main() { pthread_t tids[THREAD_NUM]; pthread_mutex_init(&mutex, NULL); // 初始化互斥锁[^2] for (int i=0; i<THREAD_NUM; i++) { pthread_create(&tids[i], NULL, thread_func, NULL); } for (int i=0; i<THREAD_NUM; i++) { pthread_join(tids[i], NULL); // 等待线程结束[^1] } printf("Final counter: %d\n", counter); // 正确输出50000 pthread_mutex_destroy(&mutex); return 0; } ``` #### 基础示例2:生产者-消费者模型 ```c #include <pthread.h> #define BUFFER_SIZE 10 int buffer[BUFFER_SIZE]; int count = 0; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void* producer(void* arg) { while (1) { pthread_mutex_lock(&mutex); if (count < BUFFER_SIZE) { buffer[count++] = 1; // 生产物品 } pthread_mutex_unlock(&mutex); } } void* consumer(void* arg) { while (1) { pthread_mutex_lock(&mutex); if (count > 0) { buffer[--count] = 0; // 消费物品 } pthread_mutex_unlock(&mutex); } } ``` §§ 1. **线程安全栈实现** 实现一个线程安全的栈结构,包含push/pop操作,要求: - 使用互斥锁保护共享数据 - 处理空栈pop时的阻塞情况 ```c // 框架参考 typedef struct { int* data; int top; pthread_mutex_t lock; } ThreadSafeStack; ``` 2. **死锁场景复现** 编写两个线程互相等待对方释放锁的代码,分析如何通过调整加锁顺序避免死锁: ```c // 线程A pthread_mutex_lock(&mutex1); pthread_mutex_lock(&mutex2); // 线程B pthread_mutex_lock(&mutex2); pthread_mutex_lock(&mutex1); ``` 3. **性能对比实验** 对比使用互斥锁(pthread_mutex)和自旋锁(pthread_spinlock)在不同竞争强度下的性能差异,设计测试方案: - 低竞争(操作间隔1ms) - 高竞争(连续操作) #### 关键知识点 1. 互斥锁必须成对使用,`lock/unlock`必须匹配 2. 可通过`pthread_mutex_trylock`实现非阻塞加锁[^3] 3. 推荐使用`PTHREAD_MUTEX_ERRORCHECK`类型锁帮助调试死锁 4. 编译时需添加`-pthread`参数: ```bash gcc program.c -pthread -o program ``` > 建议调试时注释掉加锁代码观察数据竞争现象,对比有/无锁时的程序行为差异,加深对线程同步的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值