- 浏览: 1340990 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
chinaxy1:
...
ON DUPLICATE KEY UPDATE重复插入时更新 -
b_l_east:
不一定哦,就算大小相当,in 和 exists的性能也会很大差 ...
mysql查询语句in和exists二者的区别和性能影响 -
llp1990311:
[size=x-small][/size]
如何正确防御xss攻击 -
home198979:
q315506754 写道还是佩服写c的 用其它语言一样可以实 ...
玩转深度优先搜索算法 -
q315506754:
还是佩服写c的
玩转深度优先搜索算法
1.互斥量
互斥变量用pthead_mutex_t数据类型来表示,在使用互斥变量之前,必须首先对它进行初始化,可以把它置为常量PTHREAD_MUTEX_INITIALIZER(只对静态分配的互斥量),也可以能过调用pthread_mutex_init函数进行初始化。如果动态地分配互斥量(例如通过调用malloc)函数,那么释放内存前需要使用pthread_mutex_destroy.
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexarrt_t * restrict arrt);
int pthread_mutex_destroy(pthread_mutex_t &mutex);
返回值:成功返回0,否则返回错误编号。
要用默认的属性初始化互斥量,只需把attr设置为NULL。
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
返回值:成功返回0,否则返回错误编号。
#include <stdlib.h>
#include <pthread.h>
struct foo {
int f_count;
pthread_mutex_t f_lock;
/* ... more stuff here ... */
};
struct foo *
foo_alloc(void) /* allocate the object */
{
struct foo *fp;
if ((fp = malloc(sizeof(struct foo))) != NULL) {
fp->f_count = 1;
if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {
free(fp);
return(NULL);
}
/* ... continue initialization ... */
}
return(fp);
}
void
foo_hold(struct foo *fp) /* add a reference to the object */
{
pthread_mutex_lock(&fp->f_lock);
fp->f_count++;
pthread_mutex_unlock(&fp->f_lock);
}
void
foo_rele(struct foo *fp) /* release a reference to the object */
{
pthread_mutex_lock(&fp->f_lock);
if (--fp->f_count == 0) { /* last reference */
pthread_mutex_unlock(&fp->f_lock);
pthread_mutex_destroy(&fp->f_lock);
free(fp);
} else {
pthread_mutex_unlock(&fp->f_lock);
}
}
2.避免死锁
如果线程试图对同一个互斥量加锁两次,那么它自身就会陷入死锁状态。
一个线程试图以与另一个线程相反的顺序销售互斥量时,才可能出现死锁。
实例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int lock_var;
time_t end_time;
void pthread1(void *arg);
void pthread2(void *arg);
int main(int argc, char *argv[])
{
pthread_t id1,id2;
pthread_t mon_th_id;
int ret;
end_time = time(NULL)+10;
/*互斥锁初始化*/
pthread_mutex_init(&mutex,NULL);
/*创建两个线程*/
ret=pthread_create(&id1,NULL,(void *)pthread1, NULL);
if(ret!=0)
perror("pthread cread1");
ret=pthread_create(&id2,NULL,(void *)pthread2, NULL);
if(ret!=0)
perror("pthread cread2");
pthread_join(id1,NULL);
pthread_join(id2,NULL);
exit(0);
}
void pthread1(void *arg)
{
int i;
while(time(NULL) < end_time)
{
/*互斥锁上锁*/
if(pthread_mutex_lock(&mutex)!=0)
{
perror("pthread_mutex_lock");
}
else
printf("pthread1:pthread1 lock the variable\n");
for(i=0;i<2;i++){
sleep(1);
lock_var++;
}
/*互斥锁接锁*/
if(pthread_mutex_unlock(&mutex)!=0){
perror("pthread_mutex_unlock");
}
else
printf("pthread1:pthread1 unlock the variable\n");
sleep(1);
}
}
void pthread2(void *arg)
{
int nolock=0;
int ret;
while(time(NULL) < end_time)
{
/*测试互斥锁*/
ret=pthread_mutex_trylock(&mutex);
if(ret==EBUSY)
printf("pthread2:the variable is locked by pthread1\n");
else
{
if(ret!=0)
{
perror("pthread_mutex_trylock");
exit(1);
}
else
printf("pthread2:pthread2 got lock.The variable is%d\n",lock_var);
/*互斥锁接锁*/
if(pthread_mutex_unlock(&mutex)!=0)
{
perror("pthread_mutex_unlock");
}
else
printf("pthread2:pthread2 unlock the variable\n");
}
sleep(3);
}
}
3.读写锁
1)多个读者可以同时进行读
2)写者必须互斥(只允许一个写者写,也不能读者写者同时进行)
3)写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者)
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr);
初始化读/写锁
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
锁定读/写锁
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
读取读/写锁上的锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
写读/写锁上的锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
解除读/写锁
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
成功返回0,否则返回错误编号
实例:
#include <stdlib.h>
#include <pthread.h>
struct job {
struct job *j_next;
struct job *j_prev;
pthread_t j_id; /* tells which thread handles this job */
/* ... more stuff here ... */
};
struct queue {
struct job *q_head;
struct job *q_tail;
pthread_rwlock_t q_lock;
};
/*
* Initialize a queue.
*/
int
queue_init(struct queue *qp)
{
int err;
qp->q_head = NULL;
qp->q_tail = NULL;
err = pthread_rwlock_init(&qp->q_lock, NULL);
if (err != 0)
return(err);
/* ... continue initialization ... */
return(0);
}
/*
* Insert a job at the head of the queue.
*/
void
job_insert(struct queue *qp, struct job *jp)
{
pthread_rwlock_wrlock(&qp->q_lock);
jp->j_next = qp->q_head;
jp->j_prev = NULL;
if (qp->q_head != NULL)
qp->q_head->j_prev = jp;
else
qp->q_tail = jp; /* list was empty */
qp->q_head = jp;
pthread_rwlock_unlock(&qp->q_lock);
}
/*
* Append a job on the tail of the queue.
*/
void
job_append(struct queue *qp, struct job *jp)
{
pthread_rwlock_wrlock(&qp->q_lock);
jp->j_next = NULL;
jp->j_prev = qp->q_tail;
if (qp->q_tail != NULL)
qp->q_tail->j_next = jp;
else
qp->q_head = jp; /* list was empty */
qp->q_tail = jp;
pthread_rwlock_unlock(&qp->q_lock);
}
/*
* Remove the given job from a queue.
*/
void
job_remove(struct queue *qp, struct job *jp)
{
pthread_rwlock_wrlock(&qp->q_lock);
if (jp == qp->q_head) {
qp->q_head = jp->j_next;
if (qp->q_tail == jp)
qp->q_tail = NULL;
} else if (jp == qp->q_tail) {
qp->q_tail = jp->j_prev;
if (qp->q_head == jp)
qp->q_head = NULL;
} else {
jp->j_prev->j_next = jp->j_next;
jp->j_next->j_prev = jp->j_prev;
}
pthread_rwlock_unlock(&qp->q_lock);
}
/*
* Find a job for the given thread ID.
*/
struct job *
job_find(struct queue *qp, pthread_t id)
{
struct job *jp;
if (pthread_rwlock_rdlock(&qp->q_lock) != 0)
return(NULL);
for (jp = qp->q_head; jp != NULL; jp = jp->j_next)
if (pthread_equal(jp->j_id, id))
break;
pthread_rwlock_unlock(&qp->q_lock);
return(jp);
}
这个例子中,不管什么时候需要增加一个作业也不能队列中或者从队列中删除作业,都用写模式锁住队列的读写锁。不管何时搜索队列,首先需要获取读模式下的锁,允许所有的工作线程并发地搜索队列。在这种情况下,只有线程搜索队列的频率远远高于增加或者删除作业时,使用读写锁才可能改善性能。
4.条件变量
静态创建:pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
动态创建:pthread_cond _t cond;
pthread_cond_init(&cond,NULL);
其中的第二个参数NULL表示条件变量的属性,虽然POSIX中定义了条件变量的属性,但在LinuxThread中并没有实现,因此常常忽略
实例:
#include<stdio.h>
#include<pthread.h>
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
int count=5;
void *decrement(void *arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
while(count<=0)
{
printf("count<=0,thread1 is hanging!\n");
pthread_cond_wait(&cond,&mutex);
sleep(1);
printf("sleep!\n");
}
count=count-1;
pthread_mutex_unlock(&mutex);
if(count==9)
{
printf("count=9,thread1 is over!\n");
return NULL;
}
}
}
void *increment(void *arg)
{sleep(1);
while(1)
{
pthread_mutex_lock(&mutex);
count=count+1;
if(count>0)
{
printf("count=%d,change cond state!\n",count);
pthread_cond_signal(&cond);
}
pthread_mutex_unlock(&mutex);
if(count==10)
{
printf("count=10,thread2 is over!\n");
return NULL;
}
}
}
int main()
{
int i1=1,i2=1;
pthread_t id1,id2;
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
pthread_create(&id1,NULL,decrement,NULL);
pthread_create(&id2,NULL,increment,NULL);
i2=pthread_join(id2,NULL);
i1=pthread_join(id1,NULL);
if((i2==0)&&(i1==0))
{
printf("count=%d,the main thread!\n",count);
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&mutex);
return 0;
}
}
发表评论
-
【转载】如何用Linux的命令正确识别cpu的个数和核数
2013-08-20 11:40 1925如何在Linux下cpu的个数和核数呢?googel了一下 ... -
redis2.6.9源码学习---ziplist
2013-05-16 12:05 1802ziplist相比之前分析的z ... -
redis2.6.9源码学习---zipmap
2013-05-02 17:03 2259在看此文件源码之前,先看到此文件头部的英文注释,以下是本人 ... -
redis2.6.9源码学习---zipmap
2013-05-02 14:22 0<div class="iteye-blog- ... -
非阻塞connect编程
2013-04-08 17:08 1760非阻塞模式有3种用途 1.三次握手同时做其他的处理。co ... -
C库需要注意的函数
2013-03-08 16:50 2271本文转自:http://hub.opensolaris ... -
redis2.6.9源码学习---adlist
2013-02-07 16:27 1321源码adlist.c adlist.h,先来看看adlist ... -
redis2.6.9源码学习---dict
2013-02-07 11:59 1504redis的hashtable------dict.c ... -
redis2.6.9源码学习---Big_Endian&Little_Endian
2013-02-04 10:50 2776在阅读redis源码/src/endianconv.c时遇 ... -
linux c学习笔记----SCTP基础客户/服务编程(setsockopt,sctp_sendmsg等)
2013-01-15 17:53 19707在编程之前先了解一下sctp套接字选项 setsoc ... -
linux c学习笔记----UDP基础客户/服务编程(sendto,recvfrom)
2013-01-14 18:01 53779sendto(经socket传送数据) 相关函数 ... -
linux c学习笔记----select函数详解
2013-01-11 17:25 20364select系统调用是用来让我们的程序监视多个文件句柄(fil ... -
linux c学习笔记----TCP基础客户/服务编程(socket,bind等)
2013-01-10 17:29 28464socket(建立一个socket通信) 相关 ... -
linux c学习笔记----互斥锁属性
2013-01-05 18:37 11552互斥锁属性 使用互斥锁(互斥)可以使线程按顺序执行。通 ... -
linux c学习笔记----线程属性
2013-01-04 17:38 4619一.线程属性 线程具有属性,用pthre ... -
linux c学习笔记----线程创建与终止
2012-12-14 17:32 13727进程原语 线程原语 描述 fork p ... -
linux c学习笔记----共享内存(shmget,shmat,shmdt,shmctl)
2012-12-11 18:08 36799shmgetint shmget(key_t key, siz ... -
linux c学习笔记----消息队列(ftok,msgget,msgsnd,msgrcv,msgctl)
2012-12-07 17:46 33452ftok() #include <sys/t ... -
linux信号列表
2012-11-30 16:40 2871我们运行如下命令, ... -
linux c学习笔记----信号(sigaction,sigaddset,sigprocmask)
2012-11-30 16:23 15278sigaction(查询 ...
相关推荐
线程同步-I.MX6U嵌入式Linux C应用编程学习笔记基于正点原子阿尔法开发板
这个“Linux学习笔记7-仿STM32自建寄存器库实验代码”是为了帮助理解如何在Linux环境下模拟STM32的寄存器操作,以便在没有实际硬件的情况下进行软件开发和测试。 首先,STM32是意法半导体(STMicroelectronics)...
多线程学习笔记 iOS开发中,多线程是一种常见的技术手段,用于优化应用程序的性能,提升用户体验。多线程的核心是让程序能够并发地执行多个任务,合理地利用设备的计算能力,尤其是在拥有多个核心的处理器上。 ...
在深入探讨Linux下C语言编程中进程和线程的创建之前,我们先来理解一下进程与线程的基本概念。 - **进程**:是操作系统进行资源分配和调度的基本单位,每个进程都有独立的地址空间、内存和系统资源。在Linux环境下...
以上只是部分学习笔记内容的解析,完整的笔记可能包含了更多关于文件I/O、进程管理、信号处理、线程同步等Linux C编程的核心概念。学习Linux C编程需要深入理解操作系统的工作原理,熟练掌握C语言基础,并熟悉Linux...
根据提供的文件信息,我们可以推断出这是一份关于Linux编程学习笔记的PDF资料。下面将对这份资料可能涉及的关键知识点进行详细的阐述。 ### Linux编程基础知识 #### 1. Linux操作系统概述 - **定义与特点**:Linux...
4. **线程同步**:为了确保线程间的正确执行顺序,需要进行同步操作。这包括: - **互斥锁(Mutex)**:`pthread_mutex_init()`, `pthread_mutex_lock()`, `pthread_mutex_unlock()`用于保护共享资源,防止竞态条件...
### Redis介绍 Redis是一种开源的键值存储系统,属于NoSQL数据库的一种,它与Memcached相似,但提供了数据持久化的能力。...这些内容覆盖了Redis学习笔记的主要知识点,有助于理解Redis的核心技术和应用场景。
环境C程序设计"的书籍资源,由徐诚编著,并且包含了作者的学习笔记,特别标注了重点内容和需要关注的部分,特别适合C语言的初学者作为入门材料。 C语言是一种强大的、低级的编程语言,广泛用于操作系统开发、嵌入式...
计算机基础学习笔记,包含计算机组成原理+操作系统+计算机网络。 一、计算机组成原理 todo 二、操作系统 1. 进程管理 作业管理 储存管理 文件管理 Linux 文件系统 设备管理 2. - 线程同步 -- 互斥量 - 线程同步 -- ...
{1.13}Linux命令}{41}{section.1.13} {1.13.1}基本查看、移动}{41}{subsection.1.13.1} {1.13.2}权限}{42}{subsection.1.13.2} {1.13.3}打包备份与恢复}{42}{subsection.1.13.3} {1.13.3.1}\texttt {tar},\text...
【UNIX多线程学习笔记】 在UNIX操作系统中,多线程是一种重要的编程模型,它允许多个执行流在单个进程中并发运行。多线程带来了许多优势,包括提高应用程序响应速度,充分利用多CPU系统的资源,以及优化程序结构,...
在《Linux内核设计与实现》第二版的学习笔记中,我们可以深入探讨以下几个关键知识点: 1. **内核架构**:Linux内核采用微内核架构,主要由进程管理、内存管理、文件系统、设备驱动和网络协议栈等模块组成。这些...
C语言是Linux编程的主要语言,通过学习标准IO库、系统调用、信号处理、线程与进程同步等内容,可以开发高效且稳定的程序。 4. **嵌入式Linux**:嵌入式Linux将Linux操作系统应用到资源有限的设备中,如路由器、智能...
Linux系统编程笔记涉及到的内容广泛,涵盖了从基础的出错处理到进程管理,从内存管理到进程间通信,以及守护进程设计等多个层面的知识。下面详细说明各个部分的知识点: 1. 常见出错处理 - abort函数用于异常终止...
### Linux系统编程学习笔记 #### 一、IO **1.1 标准I/O (stdio)** - **fopen/fclose**: `fopen` 用于打开或创建一个文件,并返回一个指向该文件的 `FILE *` 类型的指针。`fclose` 用于关闭由 `FILE *` 指向的文件...
以上就是Linux驱动开发学习笔记中提及的各个知识点,详细讲解了Linux驱动开发的基础知识和核心概念。每个知识点都与具体的Linux内核机制和编程实践紧密结合,是学习Linux内核驱动开发人员的宝贵资料。
这份“经典的Linux Kernel电子笔记”显然包含了深入解析Linux内核架构和功能的重要信息。以下是对其中可能包含的知识点的详细阐述: 1. **Linux内核结构**:Linux内核采用了微内核设计,主要由进程管理、内存管理、...
##### 1.4 Linux学习技巧 - **实践为主**: - 多动手操作,通过实践加深理解。 - 使用虚拟机或云环境练习。 - **资源利用**: - 学习官方文档和技术论坛。 - 加入社区和参与开源项目。 - **持续跟进**: - 关注...