社交网站第一步怎么做,免费ui网站,wordpress 多功能主题,苏州城乡和住房建设局网站首页http://blog.csdn.net/jnu_simba/article/details/9123603 一、posix 信号量 信号量的概念参见这里。前面也讲过system v 信号量#xff0c;现在来说说posix 信号量。 system v 信号量只能用于进程间同步#xff0c;而posix 信号量除了可以进程间同步#xff0c;还可以线程间…http://blog.csdn.net/jnu_simba/article/details/9123603 一、posix 信号量 信号量的概念参见这里。前面也讲过system v 信号量现在来说说posix 信号量。 system v 信号量只能用于进程间同步而posix 信号量除了可以进程间同步还可以线程间同步。system v 信号量每次PV操作可以是N但Posix 信号量每次PV只能是1。除此之外posix 信号量还有命名和匿名之分man 7 sem_overview 1、命名信号量 名字以/somename 形式分辨只能有一个/ 且总长不能超过NAME_MAX - 4一般是251。 需要用sem_open 函数创建或打开PV操作分别是sem_wait 和 sem_post可以使用sem_close 关闭删除用sem_unlink。 命名信号量用于不共享内存的进程间同步内核实现类似system v 信号量。 2、匿名信号量 存放在一块共享内存中如果是线程共享这块区域可以是全局变量如果是进程共享可以是system v 共享内存shmget 创建shmat 映射也可以是 posix 共享内存shm_open 创建mmap 映射。 匿名信号量必须用sem_init 初始化sem_init 函数其中一个参数pshared决定了线程共享还是进程共享也可以用sem_post 和sem_wait 进行操作在共享内存释放前匿名信号量要先用sem_destroy 销毁。 有关这些函数的具体参数可以man 一下。 二、互斥锁 对于多线程的程序访问冲突的问题是很普遍的解决的办法是引入互斥锁MutexMutualExclusive Lock获得锁的线程可以完成“读-修改-写”的操作然后释放锁给其它线程没有获得锁的线程只能等待而不能访问共享数据这样“读-修改-写”三步操作组成一个原子操作要么都执行要么都不执行不会执行到中间被打断也不会在其它处理器上并行做这个操作。 Mutex用pthread_mutex_t类型的变量表示pthread_mutex_init函数对Mutex做初始化参数attr设定Mutex的属性如果attr为NULL则表示缺省属性具体看结构体有人建议开发中总是设置 PTHREAD_MUTEX_RECURSIVE 属性避免死锁。 // 互斥量属性: 同一线程可多次加锁 pthread_mutexattr_t m_attr; pthread_mutexattr_init(m_attr); pthread_mutexattr_settype(m_attr, PTHREAD_MUTEX_RECURSIVE); C Code 1 2 3 4 5 6 7 8 9 10 struct pthread_mutexattr_t { enum lock_type // 使用pthread_mutexattr_settype来更改 { PTHREAD_MUTEX_TIMED_NP [default]//当一个线程加锁后其余请求锁的线程形成等待队列在解锁后按优先级获得锁。 PTHREAD_MUTEX_ADAPTIVE_NP // 动作最简单的锁类型解锁后所有线程重新竞争。 PTHREAD_MUTEX_RECURSIVE_NP // 允许同一线程对同一锁成功获得多次。当然也要解锁多次。其余线程在解锁时重新竞争。 PTHREAD_MUTEX_ERRORCHECK_NP // 若同一线程请求同一锁返回EDEADLK否则与PTHREAD_MUTEX_TIMED_NP动作相同。 } type; } attr; 用pthread_mutex_init函数初始化的Mutex可以用pthread_mutex_destroy销毁。如果Mutex变量是静态分配的全局变量或static变量也可以用宏定义PTHREAD_MUTEX_INITIALIZER来初始化相当于用pthread_mutex_init初始化并且attr参数为NULL。 一个线程可以调用pthread_mutex_lock获得Mutex如果这时另一个线程已经调用pthread_mutex_lock获得了该Mutex则当前线程需要挂起等待直到另一个线程调用pthread_mutex_unlock释放Mutex当前线程被唤醒才能获得该Mutex并继续执行。 如果一个线程既想获得锁又不想挂起等待可以调用pthread_mutex_trylock如果Mutex已经被另一个线程获得这个函数会失败返回EBUSY而不会使线程挂起等待。 上面的具体函数可以man 一下。 三、生产者消费者问题 生产者消费者问题概念参见这里。下面使用posix 信号量和互斥锁一起来演示 C Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 #include unistd.h #include sys/types.h #include pthread.h #include semaphore.h #include stdlib.h #include stdio.h #include errno.h #include string.h #define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0) #define CONSUMERS_COUNT 1 #define PRODUCERS_COUNT 1 #define BUFFSIZE 10 int g_buffer[BUFFSIZE]; unsigned short in 0; unsigned short out 0; unsigned short produce_id 0; unsigned short consume_id 0; sem_t g_sem_full; sem_t g_sem_empty; pthread_mutex_t g_mutex; pthread_t g_thread[CONSUMERS_COUNT PRODUCERS_COUNT]; void *consume(void *arg) { int i; int num (int)arg; while (1) { printf(%d wait buffer not empty\n, num); sem_wait(g_sem_empty); pthread_mutex_lock(g_mutex); for (i 0; i BUFFSIZE; i) { printf(%02d , i); if (g_buffer[i] -1) printf(%s, null); else printf(%d, g_buffer[i]); if (i out) printf(\t--consume); printf(\n); } consume_id g_buffer[out]; printf(%d begin consume product %d\n, num, consume_id); g_buffer[out] -1; out (out 1) % BUFFSIZE; printf(%d end consume product %d\n, num, consume_id); pthread_mutex_unlock(g_mutex); sem_post(g_sem_full); sleep(1); } return NULL; } void *produce(void *arg) { int num (int)arg; int i; while (1) { printf(%d wait buffer not full\n, num); sem_wait(g_sem_full); pthread_mutex_lock(g_mutex); for (i 0; i BUFFSIZE; i) { printf(%02d , i); if (g_buffer[i] -1) printf(%s, null); else printf(%d, g_buffer[i]); if (i in) printf(\t--produce); printf(\n); } printf(%d begin produce product %d\n, num, produce_id); g_buffer[in] produce_id; in (in 1) % BUFFSIZE; printf(%d end produce product %d\n, num, produce_id); pthread_mutex_unlock(g_mutex); sem_post(g_sem_empty); sleep(5); } return NULL; } int main(void) { int i; for (i 0; i BUFFSIZE; i) g_buffer[i] -1; sem_init(g_sem_full, 0, BUFFSIZE); sem_init(g_sem_empty, 0, 0); pthread_mutex_init(g_mutex, NULL); for (i 0; i CONSUMERS_COUNT; i) pthread_create(g_thread[i], NULL, consume, (void *)i); for (i 0; i PRODUCERS_COUNT; i) pthread_create(g_thread[CONSUMERS_COUNT i], NULL, produce, (void *)i); for (i 0; i CONSUMERS_COUNT PRODUCERS_COUNT; i) pthread_join(g_thread[i], NULL); sem_destroy(g_sem_full); sem_destroy(g_sem_empty); pthread_mutex_destroy(g_mutex); return 0; } 与这里的程序相比程序逻辑没太大变化只是用pthread_mutex_lock 替代了 sem_mutex其次这里是演示线程间同步现在上述程序生产者消费者各一个线程但生产者睡眠时间是消费者的5倍故消费者会经常阻塞在sem_wait(g_sem_empty) 上面因为缓冲区经常为空可以将PRODUCTORS_COUNT 改成5即有5个生产者线程和1个消费者线程而且生产者睡眠时间还是消费者的5倍从动态输出可以看出基本上就动态平衡了即5个生产者一下子生产了5份东西消费者1s消费1份刚好在生产者继续生产前消费完。 四、自旋锁和读写锁简介 一、自旋锁 自旋锁类似于互斥锁它的性能比互斥锁更高。 自旋锁与互斥锁很重要的一个区别在于线程在申请自旋锁的时候线程不会被挂起它处于忙等待的状态一般用于等待时间比较短的情形。 pthread_spin_init pthread_spin_destroy pthread_spin_lock pthread_spin_unlock 二、读写锁 1、只要没有线程持有给定的读写锁用于写那么任意数目的线程可以持有读写锁用于读 2、仅当没有线程持有某个给定的读写锁用于读或用于写时才能分配读写锁用于写 3、读写锁用于读称为共享锁读写锁用于写称为排它锁 pthread_rwlock_init pthread_rwlock_destroy int pthread_rwlock_rdlock int pthread_rwlock_wrlock int pthread_rwlock_unlock 更多有关linux中的锁问题可以参考这篇文章 《透过Linux内核看无锁编程》 http://www.ibm.com/developerworks/cn/linux/l-cn-lockfree/ 参考 《linux c 编程一站式学习》 《UNP》