- 浏览: 1331959 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
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 1881如何在Linux下cpu的个数和核数呢?googel了一下 ... -
redis2.6.9源码学习---ziplist
2013-05-16 12:05 1752ziplist相比之前分析的z ... -
redis2.6.9源码学习---zipmap
2013-05-02 17:03 2217在看此文件源码之前,先看到此文件头部的英文注释,以下是本人 ... -
redis2.6.9源码学习---zipmap
2013-05-02 14:22 0<div class="iteye-blog- ... -
非阻塞connect编程
2013-04-08 17:08 1712非阻塞模式有3种用途 1.三次握手同时做其他的处理。co ... -
C库需要注意的函数
2013-03-08 16:50 2183本文转自:http://hub.opensolaris ... -
redis2.6.9源码学习---adlist
2013-02-07 16:27 1273源码adlist.c adlist.h,先来看看adlist ... -
redis2.6.9源码学习---dict
2013-02-07 11:59 1459redis的hashtable------dict.c ... -
redis2.6.9源码学习---Big_Endian&Little_Endian
2013-02-04 10:50 2723在阅读redis源码/src/endianconv.c时遇 ... -
linux c学习笔记----SCTP基础客户/服务编程(setsockopt,sctp_sendmsg等)
2013-01-15 17:53 19652在编程之前先了解一下sctp套接字选项 setsoc ... -
linux c学习笔记----UDP基础客户/服务编程(sendto,recvfrom)
2013-01-14 18:01 53689sendto(经socket传送数据) 相关函数 ... -
linux c学习笔记----select函数详解
2013-01-11 17:25 20239select系统调用是用来让我们的程序监视多个文件句柄(fil ... -
linux c学习笔记----TCP基础客户/服务编程(socket,bind等)
2013-01-10 17:29 28393socket(建立一个socket通信) 相关 ... -
linux c学习笔记----互斥锁属性
2013-01-05 18:37 11470互斥锁属性 使用互斥锁(互斥)可以使线程按顺序执行。通 ... -
linux c学习笔记----线程属性
2013-01-04 17:38 4553一.线程属性 线程具有属性,用pthre ... -
linux c学习笔记----线程创建与终止
2012-12-14 17:32 13675进程原语 线程原语 描述 fork p ... -
linux c学习笔记----共享内存(shmget,shmat,shmdt,shmctl)
2012-12-11 18:08 36663shmgetint shmget(key_t key, siz ... -
linux c学习笔记----消息队列(ftok,msgget,msgsnd,msgrcv,msgctl)
2012-12-07 17:46 33304ftok() #include <sys/t ... -
linux信号列表
2012-11-30 16:40 2770我们运行如下命令, ... -
linux c学习笔记----信号(sigaction,sigaddset,sigprocmask)
2012-11-30 16:23 15214sigaction(查询 ...
相关推荐
【linux学习笔记--17】POSIX IPC——消息队列.doc 【linux学习笔记--18】POSIX IPC——信号量.doc 【linux学习笔记--19】POSIX IPC——共享内存.doc 【linux学习笔记-10】Linux进程相关系统调用(三).doc 【linux...
【linux学习笔记-1】使用GDB调试简单的用户程序 【linux学习笔记-2】父子进程共享文件描述符 【linux学习笔记-3】文件操作(stat,chmod,umask) 【linux学习笔记-4】进程扇和进程链 【linux学习笔记-5】编写自己的ls...
armlinux学习笔记--IIS音频驱动程序分析
ARM linux学习笔记--IIS音频驱动程序分析整理
Python学习笔记--皮大庆,非常适合零基础入门。对应英文版本《How to think like a computer scientist》
c语言学习笔记-简易版扫雷
认真学习的人从国内某个培训机构上课时,记录的C语言学习笔记,其中包含所有的C语言基本语法,文章中对指针、字符操作有好多介绍,整理的很全面,并且有图示哦!! 相信对大家学习C语言会有很大帮助!!!
C语言学习笔记-详细而全面的基础教程.pdf
JXW的C语言学习笔记-待查
写得蛮好的linux学习笔记--linux目录架构
linux内核移植 笔记--移植指令 linux内核移植 笔记--移植指令 linux内核移植 笔记--移植指令
armlinux学习笔记--触摸屏驱动程序分析.pdf
Linux课程学习笔记 -韩顺平 包含c/c++/python/java 专项 面试题 PDF PPT 笔记 面试题 (百度网盘链接 永久有效) 自学,做笔记,复习可用
armlinux学习笔记--IIS音频驱动程序分析(2).pdf
Linux学习笔记Linux学习笔记Linux学习笔记Linux学习笔记
armlinux学习笔记--IIS音频驱动程序分析(2)资料.pdf
linux学习笔记-01linux操作基础
找到的一篇写的很好的linux学习笔记 不敢独享 大家有兴趣的就下下
Linux学习笔记-超全总结值得一看(带标签目录),共154页。
python爬虫学习笔记-scrapy框架(1) python scrapy 爬虫 python爬虫学习笔记-scrapy框架(1) python scrapy 爬虫 python爬虫学习笔记-scrapy框架(1) python scrapy 爬虫 python爬虫学习笔记-scrapy框架(1) python ...