【Linux】线程互斥

线程最大的特性就是可以一个代码,多个线程同时执行,从而极大地提升程序的运行速度。然而,在线程并发的同时要注意,互斥的情况,比如如下的一个模拟一个最近话题的抢票程序,显然设定的三个线程仅能有一个线程得到票,否则票会撕烂,其实,这个程序在《【Java】利用synchronized(this)完成线程的临界区》(点击打开链接)已经详细说过了,只是这次的编程环境编程了LinuxC。

如下的线程互斥的程序,可以看到这个mutex程序的运行结果由于操作系统对线程的资源分配的不同而不同。


具体代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t mutex;//声明一个互斥锁mutex
int ticket=10;
void *thread_function(void *arg){
	while(ticket>0){
		if(pthread_mutex_lock(&mutex)!=0){//对互斥锁上锁,临界区开始
			printf("%s的互斥锁创建失败!\n",(char *)arg);
			pthread_exit(NULL);
		}
		if(ticket>0){//如果还有票
			ticket--;
			printf("%s拿到了票,现在票量剩余:%d\n",(char *)arg,ticket);
			sleep(1);//该线程挂起1秒
		}
		else{//否则退出
			pthread_exit(NULL);//退出线程
		}
		pthread_mutex_unlock(&mutex);//解锁,临界区结束
		sleep(1);//该线程挂起1秒
	}
	pthread_exit(NULL);//退出线程
}
int main(){
	pthread_mutex_init(&mutex,NULL);//初始化这个互斥锁
	//声明并创建三个线程
	pthread_t t1;
	pthread_t t2;
	pthread_t t3;
	if(pthread_create(&t1,NULL,thread_function,"线程1")!=0){
		printf("创建线程失败!程序结束!\n");
		exit(1);
	}
	if(pthread_create(&t2,NULL,thread_function,"线程2")!=0){
		printf("创建线程失败!程序结束!\n");
		exit(1);
	}
	if(pthread_create(&t3,NULL,thread_function,"线程3")!=0){
		printf("创建线程失败!程序结束!\n");
		exit(1);
	}
	pthread_join(t1,NULL);
	pthread_join(t2,NULL);
	pthread_join(t3,NULL);
	//三个线程都完成才能执行以下的代码
	pthread_mutex_destroy(&mutex);//销毁这个互斥锁
	return 0;
}

LinuxC线程的使用,在《【Linux】线程》( 点击打开链接)已经讲过了,这里主要讲互斥。线程互斥锁,应该作为全局变量声明,因为线程互斥锁会在主函数声明,线程执行函数内使用,之后,在主函数新建的三个线程,共同执行void *thread_function(void *arg);中的代码。

三个线程形成的互斥关系如下所示:


其实这与java本身就有的关键字synchronized是一模一样的,唯一不同是,LinuxC中的互斥锁还要自己声明,初始化,销毁而已。

### Linux 环境下线程互斥锁 `pthread_mutex` 的使用 在 Linux 编程环境中,`pthread_mutex_t` 是用于实现多线程间同步的一种机制。它通过提供加锁和解锁功能来保护共享资源免受并发访问的影响。 #### 初始化互斥锁 可以通过两种方式初始化互斥锁: 1. **静态初始化** 使用宏 `PTHREAD_MUTEX_INITIALIZER` 对互斥锁进行静态初始化。这种方式适用于全局变量或静态变量的场景。 ```c pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ``` 2. **动态初始化** 调用函数 `pthread_mutex_init()` 动态创建并初始化互斥锁。此方法允许指定额外的属性参数(通常设置为 NULL 表示默认属性)。 ```c pthread_mutex_t mutex; int result = pthread_mutex_init(&mutex, NULL); if (result != 0) { perror("Mutex initialization failed"); exit(EXIT_FAILURE); } ``` #### 加锁与解锁操作 为了确保多个线程不会同时访问同一段临界区代码,在进入该区域前需调用 `pthread_mutex_lock()` 或其非阻塞版本 `pthread_mutex_trylock()` 进行锁定;完成工作后应立即释放锁以避免死锁情况发生。 - **加锁** ```c int lock_result = pthread_mutex_lock(&mutex); if(lock_result != 0){ perror("Failed to acquire the lock."); // Handle error appropriately. } ``` - **尝试加锁(非阻塞)** 如果当前无法获取到锁,则返回错误码而不是等待。 ```c int trylock_result = pthread_mutex_trylock(&mutex); if(trylock_result == EBUSY){ printf("Lock is busy.\n"); }else{ // Proceed with critical section... } ``` - **解锁** 当前线程结束对共享数据的操作之后应当及时解除对该对象上的任何控制权以便其他可能正在排队等候它的进程可以继续运行下去。 ```c int unlock_result = pthread_mutex_unlock(&mutex); if(unlock_result != 0){ perror("Unlocking mutex failed."); // Error handling code here as needed. } ``` #### 销毁互斥锁 当不再需要某个特定类型的互斥体实例时应该销毁它们从而回收内存空间以及减少不必要的开销。 ```c int destroy_result = pthread_mutex_destroy(&mutex); if(destroy_result != 0){ perror("Destroying mutex encountered an issue."); } ``` 以下是完整的例子展示如何在线程之间安全地更新计数器值: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> // Define global variables and initialize them properly. long counter = 0L; pthread_mutex_t count_mutex; void* increase_counter(void* arg){ long i; for(i=0;i<1000000;i++){ pthread_mutex_lock(&count_mutex); // Lock before modifying shared resource. counter +=1 ; pthread_mutex_unlock(&count_mutex); // Unlock after modification finished. } return NULL; } int main(){ pthread_t thread_one,thread_two; /* Initialize Mutex */ if(pthread_mutex_init(&count_mutex,NULL)!=0){ fprintf(stderr,"Error initializing mutex\n"); return EXIT_FAILURE; } /* Create threads that will increment our counter variable safely using locks.*/ if(pthread_create(&thread_one,NULL,increase_counter,(void*)NULL)){ fprintf(stderr,"Thread creation failed!\n"); goto cleanup_mutex; } if(pthread_create(&thread_two,NULL,increase_counter,(void*)NULL)){ fprintf(stderr,"Second Thread Creation Failed!"); goto join_first_thread; } /* Wait until both threads finish their job*/ pthread_join(thread_one,NULL); join_first_thread: pthread_join(thread_two,NULL); cleanup_mutex: pthread_mutex_destroy(&count_mutex); printf("Final Counter Value:%ld\n",counter); return EXIT_SUCCESS; } ``` 上述程序展示了两个独立工作的线程共同增加同一个整型数值的过程,并且每次修改之前都会先获得相应的互斥锁,这样就防止了竞争条件的发生。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值