多线程编程同步问题(C、Linux)

下面我们要讨论多线程编程环境下用于线程同步的方式,有:POSIX信号量、互斥量、条件变量。

POSIX信号量

POSIX信号量函数有五个如下:

#include<semaphore.h>

int sem_init(sem* sem, int pshared, unsigned int value);
int sem_destroy(sem_t* sem);
int sem_wait(sem_t* sem);
int sem_trywait(sem_t* sem);
int sem_post(sem_t* sem);

sem_int函数用于初始化一个信号量(POSIX支持有名信号量,这里不讨论),pshared如果是0就表示这个信号量是当前进程的局部信号量(其他值的话用于进程共享,不讨论),value指定信号量的初始值。一定要注意不要初始化一个已经初始化的信号量

sem_desroty函数用于释放信号量,一定要注意不要去destroy一个正在被占用的信号量。

sem_wait将信号量的value减1,如果value是0,sem_wait将被阻塞,直到这个信号量的值非0。

sem_trywait与sem_wait相似,只是它不阻塞,无论value是否是非零,他都返回。如果value是0,他会返回-1并设置errno为EAGAIN。

sem_post函数将信号量加1,当然这个操作是原子操作,如果信号量的值大于0,其他被sem_wait等待的线程将被唤醒。

互斥锁

#include <pthread.h>

int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* mutexattr);
int pthread_mutex_destroy(pthread_mutex_t* mutex);
int pthread_mutex_lock(pthread_mutex_t* mutex);
int pthread_mutex_unlock(pthread_mutex_t* mutex);
int pthread_mutex_trylock(pthread_mutex_t* mutex);

pthread_mutex_t是一个结构体类型,pthread_mutexattr_t结构体定义的是互斥锁属性(如果设置为NULL就是默认属性)。

init函数用来初始化互斥锁,destory函数用来销毁锁(当然得注意不要销毁一个正在被占用的互斥锁),

lock加锁,unlock解锁,当然trylock是非阻塞版本,失败就会返回错误码。

条件变量

#include <pthread.h>

int pthread_cond_init(pthread_cond_t* cond, const pthread_condattr_t* cond_attr);
int pthread_cond_destroy(pthread_cond_t* cond);
int pthread_cond_broadcast(pthread_cond_t* cond);
int pthread_cond_signal(pthread_cond_t* cond);
int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex);

init函数用于初始化一个条件变量,如果cond_attr是NULL,那么就按默认属性初始化

destroy销毁条件变量,如果条件变量正在被使用则返回EBUSY错误码(和前两个不同).

broadcast唤醒所有等待的线程,signal唤醒一个,至于是哪一个取决于线程的优先级和调度策略.

wait函数调用前一定要确保 mutex上锁,wait函数的调用会先将调用线程放入条件变量的等待队列中,然后将互斥量解锁.显然wait函数执行将调用线程放入条件变量的等待队列中这个过程, signal,broadcast函数不会修改条件变量,换一句话说就是wait函数不会错过条件变量的任何变化. wait函数返回成功后mutex会被继续上锁.

生产者消费者模型

下面是关于条件变量的测试代码,条件变量结合互斥锁经常被用到生产者和消费者模型中,

这里要注意的是条件变量最好放在while里面,下面例子可以用if代替.至于为什么放在while里面比较好,读者可以自己研究.

#include <pthread.h>
#include <list>
#include <stdio.h>
#include <unistd.h>
using namespace std;

pthread_mutex_t list_mutex = PTHREAD_MUTEX_INITIALIZER;//静态初始化
pthread_cond_t cond_em = PTHREAD_COND_INITIALIZER;

list<long> my_list;
void* consume(void* arg)
{
	while(1)
	{
		pthread_mutex_lock(&list_mutex);
		while(my_list.empty())
		{
			pthread_cond_wait(&cond_em, &list_mutex);
		}
		printf("value = %d\n", my_list.back());
		my_list.pop_back();
		pthread_mutex_unlock(&list_mutex);
		sleep(1);
	}
	
}

void* produce(void* arg)
{
	long temp = (long)arg;
	while(1)
	{
		pthread_mutex_lock(&list_mutex);
		my_list.push_back(temp);
		pthread_mutex_unlock(&list_mutex);
		pthread_cond_signal(&cond_em);
		sleep(1);
	}
}


int main()
{
	int i = 0;
	pthread_t* pid = new pthread_t[10];
	for(; i < 5; ++i)
	{
		pthread_create(pid+i, NULL, &produce, (void*)i);
	}
	for(; i < 10; ++i)
	{
		pthread_create(pid+i, NULL, &consume, (void*)i);
	}
	--i;
	sleep(10);
	for(; i>=0; --i)
	{
		pthread_join(pid[i], NULL);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux线编程是一种技术,可以让一个程序并行地处理多个任务。它可以提高程序的执行效率,更有效地使用计算机的资源,并减少系统响应时间。Linux 是一种流行的操作系统,支持多线编程。多线编程是指在同一进程中同时执行多个线程,每个线程执行自己的任务。下面是一些关于 Linux线编程的基本概念和技术: 1. 线程和进程的区别:线程是进程内的一个执行单元,进程是操作系统分配资源的一个独立单位。 2. 线同步线同步是指协调多个线程之间的执行顺序,防止出现数据竞争和死锁等问题。常见的线同步技术包括互斥量、条件变量和信号量等。 3. 线程池:线程池是一种预先创建一组线程并重复使用的技术。线程池可以提高多线程程序的效率和性能。 4. POSIX 线程库:POSIX 线程库是 Linux 操作系统支持的一种多线编程接口,提供了一套标准的多线程 API,包括创建、销毁、同步和调度线程等功能。 5. 多线程调试:多线程程序的调试需要注意避免数据竞争和死锁等问题,可以使用调试工具和技术,如 gdb 和 Valgrind 等。 总之,多线编程Linux 程序员必备的技能之一,掌握多线编程技术可以提高程序的效率和性能,同时也需要注意避免常见的线问题。 ### 回答2: Linux线编程是一种在 Linux 操作系统上开发并行应用程序的方式,它允许一个程序同时执行多个线程,从而提高程序的响应速度和运行效率。在 Linux 中,线程是轻量级的进程,它们共享同一进程的资源和数据,可以同时运行在不同的 CPU 核心上,使得程序在多核系统中具有更好的性能表现。 Linux 提供了多种多线编程的 API,其中最常用的是 pthreads 库,它是一组 C 语言函数,可用于创建、同步和管理多个线程。使用 pthreads 库编写多线程程序的基本步骤包括定义线程函数、创建线程、执行线程、同步线程和销毁线程,这些步骤需要程序员显式地调用相关的 API 函数来实现。 在编写多线程程序时,必须考虑线程之间的共享资源和同步问题。共享资源包括程序的数据、文件、网络连接等,可以使用临界区、互斥锁、信号量等技术来保护。同步问题则是确保多个线程之间按照正确的顺序执行,不会产生死锁、饥饿等问题,可以使用信号量、互斥锁、条件变量等技术来实现。 此外,多线编程还需要考虑到线程的调度问题,即如何让不同的线程在不同的时间片内执行,从而实现线程的抢占和优先级控制。Linux 提供了优先级调度器和时间片分配器来实现线程的调度,程序员可以根据需要设定优先级和时间片长度来控制线程的执行顺序和时间切片。 总之,Linux线编程是一种高效、灵活和可扩展的编程模型,能够充分利用多核系统的性能,并实现程序的并行化和异步化。开发者需要熟悉多线编程的基本概念、API 和技术,遵循正确的资源共享和同步策略,才能编写出高质量、可靠、并发的多线程程序。 ### 回答3: Linux线编程是指在 Linux 操作系统下使用多个线程同时运行程序来提高程序的运行效率、并实现多任务处理。多线编程具有使用方便、管理灵活、响应速度相对于进程更快的优势,常被应用于高并发服务器中。 在 Linux 中,多线编程的实现主要依赖于 pthread 库。该库提供了一些线程函数和数据结构,用于创建、控制、同步和分离线程等操作。以下是一些常用的 pthread 函数: 1. pthread_create():用于创建一个新线程; 2. pthread_join():主线程阻塞等待子线程结束; 3. pthread_exit():用于在线程代码中退出线程; 4. pthread_mutex_lock():线程加锁; 5. pthread_mutex_unlock():线程解锁; 6. pthread_cond_wait():线程等待; 7. pthread_cond_signal():唤醒等待的线程。 除了 pthread 库,Linux 还提供了其它一些可用于多线编程的工具和技术,如: 1. OpenMP:一种基于共享内存的多线编程模型; 2. MPI:一种消息传递的分布式并行编程模型。 当进行多线编程时,需要注意以下几个方面: 1. 多线编程的并发性可能会导致一些竞态条件,需要使用锁或互斥量进行同步; 2. 在实现多线编程过程中,应该尽量避免使用全局变量或静态变量; 3. 在多线编程实践中,应注意资源的释放和内存泄漏的问题。 总之,Linux线编程是一项非常重要的技能,它能够在提高程序性能和响应速度方面发挥重要作用。熟练掌握多线编程技术,对于编写高效稳定的服务端程序和优化多线程应用程序的性能都非常有益。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值