文档章节

linux 下C语言线程示例 + 线程同步

宁宁爸
 宁宁爸
发布于 2016/07/29 17:29
字数 1663
阅读 195
收藏 3
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

typedef struct ct_sum {
	int sum;
	pthread_mutex_t lock;
} ct_sum;

void * add1(void * cnt) {

	pthread_mutex_lock(&(((ct_sum*) cnt)->lock));
	int i;
	for (i = 0; i < 50; i++) {
		(*(ct_sum*) cnt).sum += i;
	}
	pthread_mutex_unlock(&(((ct_sum*) cnt)->lock));
	pthread_exit(NULL);
	return 0;
}

void * add2(void *cnt) {
	int i;
	cnt = (ct_sum*) cnt;
	pthread_mutex_lock(&(((ct_sum*) cnt)->lock));
	for (i = 50; i < 101; i++) {
		(*(ct_sum*) cnt).sum += i;
	}
	pthread_mutex_unlock(&(((ct_sum*) cnt)->lock));
	pthread_exit(NULL);
	return 0;
}

int main(void) {
	int i;
	pthread_t ptid1, ptid2;
	int sum = 0;
	ct_sum cnt;
	pthread_mutex_init(&(cnt.lock), NULL);
	cnt.sum = 0;
	pthread_create(&ptid1, NULL, add1, &cnt);
	pthread_create(&ptid2, NULL, add2, &cnt);

	pthread_mutex_lock(&(cnt.lock));
	printf("sum %d\n", cnt.sum);
	pthread_mutex_unlock(&(cnt.lock));
	pthread_join(ptid1, NULL);
	pthread_join(ptid2, NULL);
	pthread_mutex_destroy(&(cnt.lock));
	return 0;
}

linux下为了多线程同步,通常用到锁的概念。

 

          互斥锁是一种通过简单的加锁的方法来控制对共享资源的存取,用于解决线程间资源访问的唯一性问题。互斥锁有上锁和解锁两种状态,在同一时刻只能有一个线程掌握某个互斥的锁,拥有上锁状态的线程可以对共享资源进行操作。若其他线程希望对一个已经上了锁的互斥锁上锁,则该线程会被挂起,直到上锁的线程释放掉互斥锁为止。

         posix下抽象了一个锁类型的结构:ptread_mutex_t。通过对该结构的操作,来判断资源是否可以访问。顾名思义,加锁(lock)后,别人就无法打开,只有当锁没有关闭(unlock)的时候才能访问资源。
        它主要用如下5个函数进行操作。
        1:pthread_mutex_init(pthread_mutex_t * mutex,const pthread_mutexattr_t *attr);  初始化锁变量mutex。attr为锁属性,NULL值为默认属性。
        2:pthread_mutex_lock(pthread_mutex_t *mutex);加锁
        3:pthread_mutex_tylock(pthread_mutex_t *mutex);加锁,但是与2不一样的是当锁已经在使用的时候,返回为EBUSY,而不是挂起等待。
        4:pthread_mutex_unlock(pthread_mutex_t *mutex);释放锁

        5:pthread_mutex_destroy(pthread_mutex_t *mutex);使用完后释放

 

     1.创建和销毁

 

 动态方式是采用pthread_mutex_init()函数来初始化互斥锁,API定义如下: int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr) 其中mutexattr用于指定互斥锁属性(见下),如果为NULL则使用缺省属性。  有两种方法创建互斥锁,静态方式和动态方式。POSIX定义了一个宏PTHREAD_MUTEX_INITIALIZER来静态初始化互斥锁,方法如下: pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; 在LinuxThreads实现中,pthread_mutex_t是一个结构,而PTHREAD_MUTEX_INITIALIZER则是一个结构常量。

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

     2.互斥锁属性

* PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。  互斥锁的属性在创建锁的时候指定,在LinuxThreads实现中仅有一个锁类型属性,不同的锁类型在试图对一个已经被锁定的互斥锁加锁时表现不同。当前(glibc2.2.3,linuxthreads0.9)有四个值可供选择:

* PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。

* PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同。这样就保证当不允许多次加锁时不会出现最简单情况下的死锁。

* PTHREAD_MUTEX_ADAPTIVE_NP,适应锁,动作最简单的锁类型,仅等待解锁后重新竞争。

    3.锁操作

int pthread_mutex_lock(pthread_mutex_t *mutex)  锁操作主要包括加锁pthread_mutex_lock()、解锁pthread_mutex_unlock()和测试加锁 pthread_mutex_trylock()三个,不论哪种类型的锁,都不可能被两个不同的线程同时得到,而必须等待解锁。对于普通锁和适应锁类型,解锁者可以是同进程内任何线程;而检错锁则必须由加锁者解锁才有效,否则返回EPERM;对于嵌套锁,文档和实现要求必须由加锁者解锁,但实验结果表明并没有这种限制,这个不同目前还没有得到解释。在同一进程中的线程,如果加锁后没有解锁,则任何其他线程都无法再获得锁。

int pthread_mutex_unlock(pthread_mutex_t *mutex)

int pthread_mutex_trylock(pthread_mutex_t *mutex)

pthread_mutex_trylock()语义与pthread_mutex_lock()类似,不同的是在锁已经被占据时返回EBUSY而不是挂起等待。

   4.其他

这个锁机制同时也不是异步信号安全的,也就是说,不应该在信号处理过程中使用互斥锁,否则容易造成死锁。POSIX 线程锁机制的Linux实现都不是取消点,因此,延迟取消类型的线程不会因收到取消信号而离开加锁等待。值得注意的是,如果线程在加锁后解锁前被取消,锁将永远保持锁定状态,因此如果在关键区段内有取消点存在,或者设置了异步取消类型,则必须在退出回调函数中解锁。

互斥锁属性使用互斥锁(互斥)可以使线程按顺序执行。通常,互斥锁通过确保一次只有一个线程执行代码的临界段来同步多个线程。互斥锁还可以保护单线程代码。

 

 互斥锁的一个明显缺点是它只有两种状态:锁定和非锁定。而条件变量通过允许线程阻塞和等待另一个线程放松信号的方法弥补了互斥锁的不足,它常和互斥锁一块使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其他的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正在被此条件阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。条件变量上的基本操作有两个。1.触发条件:当条件变为true时;2.等待条件:挂起线程直到其他线程触发条件。条件变量的数据类型是pthreead_cond_t,在使用前也需要初始化。

 

 

本文转载自:http://blog.csdn.net/edonlii/article/details/8486960

宁宁爸
粉丝 82
博文 58
码字总数 26478
作品 0
高级程序员
私信 提问
pthread多线程(C语言) + Socket

pthread多线程(C语言) + Socket pthread是使用使用C语言编写的多线程的API, 简称Pthreads ,是线程的POSIX标准,可以在Unix / Linux / Windows 等系统跨平台使用。在类Unix操作系统(Unix、...

风清水遥
01/31
0
0
Python标准库08 多线程与同步 (threading包)

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢! Python主要通过标准库中的threading包来实现多线程。在当今网络时代,每个服务器都会接收到大量的请求...

osDaniel
2014/09/21
34
0
C语言中的多线程编程

很久很久以前,我对C语言的了解并不是很多,我最早听说多线程编程是用Java,其实C语言也有多线程编程,而且更为简单、方便、强大。下面就让我们简单领略一下Unix C语言环境下的多线程编程吧!...

红薯
2011/04/28
1K
5
iOS中的“锁事”

抛砖引玉 说到锁不得不提线程安全,说到线程安全,作为iOS程序员又不得不提 与 不会对生成的 、 方法加同步锁(非原子性) 会对生成的 、 加同步锁(原子性) / 被 修饰的属性时,该属性是读...

Dalla尹
2017/12/01
0
0
Linux 多线程应用中编写安全的信号处理函数

Linux 多线程应用中编写安全的信号处理函数 在 开发多线程应用时,开发人员一般都会考虑线程安全,会使用 pthread_mutex 去保护全局变量。如果应用中使用了信号,而且信号的产生不是因为 程序...

WuHonghai
2012/05/10
303
0

没有更多内容

加载失败,请刷新页面

加载更多

iOS苹果应用IPA一键签名工具及重签教程

开心签名工具,是一款跨平台ios签名和重签名工具。 同时支持在windows、linux、mac运行,数据同步,方便使用及管理! 开心重签名工具官网 功能特点 1、支持图形界面及命令行重签(部署到服务...

tintong
16分钟前
3
0
2.4G有源卡核心芯片供应商

有源2.4G RFID的防盗标签,在与无源标签相比较,通信距离远,通信时效高。我司的SI24R2E这颗芯片专门为2.4G有源标签而设计,具有低功耗,发送距离远,厂商设计简单等优势;广泛应用于现在城市...

文刀石
21分钟前
2
0
设置Ubuntu16.04启动为命令行界面

1. 修改/etc/default/grub文件,将GRUB_CMDLINE_LINUX_DEFAULT设置成”quiet splash 3” 2. 使用命令update-grub使得在/boot下重新生成GRUB2配置文件。 3. 重启...

JosiahMg
22分钟前
3
0
C++基础知识点

计算机语言 计算机不能理解高级语言,只能理解机器语言,必须要将高级语言翻译成机器语言,翻译的方式有两种,一种是编译,一种是解释 解释型语言,在运行程序时进行翻译,每个语句在执行时逐...

大瑞清_liurq
28分钟前
2
0
EFCore 多条数据更新不能同时savechanges()的解决方法

1 在ModelContext定义下增加var transaction = ctx.Database.BeginTransaction(); 1.2 在最后一个SaveChanges()后增加transaction.Commit(); 3 在finally的if (sMsgCode != "")分支中增加tra......

_Somuns
32分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部