线程间同步实现--通过互斥锁和条件变量
2012-11-04 00:58
375 查看
信号量是一种用于提供不同进程或一个给定进程的不同线程间同步手段。
在Posix中,已经有一套信号接口,用于同一个进程中不同线程同步,其接口为:
但Posix标准实现信号量的主要的目的是提供一种进程间同步的方式,注意重点是解决进程间,不过信号量也可以用于线程间同步。
进程间同步通过有名信号量(sem_open(), sem_close(), sem_unlink(), sem_wait(), sem_post(), sem_getvalue(), sem_trywait())
线程间同步一般通过互斥锁和条件变量来实现,但具体情况,还要看应用场景。
下面主要介绍通过互斥锁和条件变量实现信号实现,代码比较简单:
在Posix中,已经有一套信号接口,用于同一个进程中不同线程同步,其接口为:
int sem_init(sem_t *sem, int pshared, unsigned int value); int sem_wait(sem_t *sem); int sem_trywait(sem_t *sem); int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); int sem_destroy(sem_t *sem); int sem_getvalue(sem_t *sem);
但Posix标准实现信号量的主要的目的是提供一种进程间同步的方式,注意重点是解决进程间,不过信号量也可以用于线程间同步。
进程间同步通过有名信号量(sem_open(), sem_close(), sem_unlink(), sem_wait(), sem_post(), sem_getvalue(), sem_trywait())
线程间同步一般通过互斥锁和条件变量来实现,但具体情况,还要看应用场景。
下面主要介绍通过互斥锁和条件变量实现信号实现,代码比较简单:
#ifndef __DL_SEMA_H__ #define __DL_SEMA_H__ #ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif typedef void* dl_sema_t; extern int dl_sema_create(dl_sema_t *pSema, unsigned int init_cnt); extern int dl_sema_destroy(dl_sema_t sema); extern int dl_sema_p(dl_sema_t sema, int timeout); extern int dl_sema_v(dl_sema_t sema); #ifdef __cplusplus #if __cplusplus } #endif #endif #endif /* __DL_SEMA_H__ */
#include <pthread.h> #include <stdlib.h> #include <sys/time.h> /* gettimeofday() */ #include "dl_sema.h" #ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif #define SEMA_MAGIC 0xF147258F struct sema_info{ unsigned int magic; int cnt; pthread_mutex_t mutex; pthread_cond_t cond; }; /* abstime = millsec + the current time */ void dl_gettime(struct timespec *abstime, int millsec) { long sec, nsec; struct timeval cur_time; gettimeofday(&cur_time, 0); nsec = cur_time.tv_usec * 1000; sec = cur_time.tv_sec; nsec += (millsec%1000)*1000000; abstime->tv_nsec = nsec % 1000000000; sec += millsec/1000; sec += nsec / 1000000000; abstime->tv_sec = sec; } /* create a semaphore with init_cnt */ int dl_sema_create(dl_sema_t *pSema, unsigned int init_cnt) { struct sema_info *sema; if(!pSema) return -1; sema = malloc(sizeof(struct sema_info)); if(!sema) return -1; if(pthread_mutex_init(&(sema->mutex), 0) != 0){ free(sema); return -1; } if( pthread_cond_init(&(sema->cond), 0) != 0){ pthread_mutex_destroy(&(sema->mutex)); free(sema); return -1; } sema->cnt = init_cnt; sema->magic = SEMA_MAGIC; *pSema = sema; return 0; } int dl_sema_p(dl_sema_t sema, int timeout) { struct sema_info *psema = (struct sema_info*) sema; int ret = 0; if(!psema || (psema->magic != SEMA_MAGIC) ) return -1; pthread_mutex_lock(&(psema->mutex)); if(psema->cnt <= 0){ /* wait forever */ if(timeout == 0){ while(psema->cnt <= 0){ if((ret = pthread_cond_wait(&(psema->cond), &(psema->mutex))) != 0){ pthread_mutex_unlock(&(psema->mutex)); return ret; } } } else { struct timespec abs_time; dl_gettime(&abs_time, timeout); while(psema->cnt <= 0){ ret = pthread_cond_timedwait(&(psema->cond), &(psema->mutex), &abs_time); if(ret != 0){ pthread_mutex_unlock(&(psema->mutex)); return ret; } } } } psema->cnt--; pthread_mutex_unlock(&(psema->mutex)); return 0; } int dl_sema_v(dl_sema_t sema) { int ret = 0; struct sema_info* psema = (struct sema_info*)sema; if(!psema || (psema->magic != SEMA_MAGIC) ) return -1; pthread_mutex_lock(&(psema->mutex)); psema->cnt++; ret = pthread_cond_signal(&(psema->cond)); if(ret != 0){ psema->cnt--; /* roll back */ pthread_mutex_unlock(&(psema->mutex)); return ret; } pthread_mutex_unlock(&(psema->mutex)); return 0; } int dl_sema_destroy(dl_sema_t sema) { struct sema_info* psema = (struct sema_info*)sema; int ret = 0; if(!psema || (psema->magic != SEMA_MAGIC) ) return -1; psema->magic = 0; if((ret = pthread_mutex_destroy(&(psema->mutex))) != 0) return ret; if((ret = pthread_cond_destroy(&(psema->cond))) != 0) return ret; free(psema); return 0; } #ifdef __cplusplus #if __cplusplus } #endif #endif
//简单测试代码: #include <stdio.h> #include <pthread.h> #include <stdlib.h> #include "dl_sema.h" void *thread_1(void *arg) { int ret; dl_sema_t sema = (dl_sema_t)arg; ret = dl_sema_p(sema, 3000);/* 3s timeout */ if(ret == 0)printf("the semaphore come up !\n"); dl_sema_destroy(sema); return 0; } void *thread_2(void *arg) { dl_sema_t sema = (dl_sema_t)arg; dl_sema_v(sema); printf("OK!!!!\n"); return 0; } int main(int argc, char**argv) { pthread_t thid; dl_sema_t sema; if(dl_sema_create(&sema, 0)) printf("dl_sema_init failed.\n"); pthread_create(&thid, 0, thread_1, sema); pthread_create(&thid, 0, thread_2, sema); sleep(5); return 0; }
相关文章推荐
- 线程的同步控制---信号量、互斥锁、条件变量
- 线程的同步:通过同步方法实现
- Linux进程间通信IPC学习笔记之同步一(线程、互斥锁和条件变量)
- Linux多线程编程之线程结合互斥锁实现同步
- linux 线程的同步 二 (互斥锁和条件变量)
- 线程间同步,条件变量,互斥锁的使用
- 利用条件变量实现线程间同步
- 利用条件变量实现线程间同步
- linux线程间同步(1)互斥锁与条件变量
- 嵌入式开发之hi3519---进程线程间的同步和互斥,条件变量、信号了、互斥锁等
- 通过SQL Server 2008数据库复制实现数据库同步备份
- Java总结(十)—实现Runnable接口创建线程,线程安全同步,死锁(哲学家进餐问题),读写锁
- Enterprise Library深入解析与灵活应用(2): 通过SqlDependency实现Cache和Database的同步
- python使用互斥锁同步线程
- 跨线程访问[同步]的简单实现[Invoke][C#]
- 同步工具之Exchanger实现线程间的数据交换
- Java并发编程中级篇(四):使用CyclicBarrier实现并发线程在集合点同步
- 表级数据同步:通过merge,database links,procedure,job实现
- Visual C++利用互斥量同步线程实现文件读取进度条
- rsync 通过密码文件实现远程同步