- 浏览: 724560 次
- 性别:
- 来自: 北京
最新评论
-
wxweven:
Surmounting 写道既然 Java 的跳表那么少,我决 ...
SkipList 跳表 -
暮雪云然:
写的不错,很透彻
Java静态内部类 -
bzhao:
好,赞扬!
Linux信号详解 -
jacktao219:
赞一个~! ,现在正在看redis 所以接触到跳表
SkipList 跳表 -
is_leon:
vote--后还要判断是否为0吧,如果为0则废掉重新置位can ...
现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
1 互斥变量: pthread_mutex_t,本质上说是一把锁,在访问共享资源前对互斥量加锁,访问完成后释放锁。
对互斥量进行加锁后,任何其他试图再次对互斥量加锁的线程将会被阻塞直至当前线程释放该互斥锁。
pthread_mutex_lock : 加锁
pthread_mutex_unlock:解锁
2 条件变量:pthread_cond_t,多个线程协作的一种同步方式,若某个条件不满足,线程将一直等待。条件变量一般
和互斥变量一起配合使用,因为条件变量本身是互斥访问的,所以要有一个互斥变量保护它。
pthread_cond_wait: 若条件不满组,一直等待下去
pthread_cond_signal: 把条件变量设为满足状态
3 实例: 两个线程,共同操作消息队列,线程1不断产生消息,添加到消息队列中,线程2不断处理消息队列中的消息
若消息队列为空,则等待直到有新的消息。写一个程序模拟此过程。
设置一个条件变量, pthread_cond_t qready, 表示消息队列不为空
设置一个互斥变量, pthread_mutex_t mutex, 用来保护qready和消息队列的互斥访问
代码如下:
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #define SIZE 10000 typedef struct msg_t { int data; struct msg_t *next; } msg_t; typedef struct global_t { msg_t *workq; pthread_cond_t qready; pthread_mutex_t qlock; int size; /* 队列中待处理的消息数量 */ } global_t; void *process_msg(void *arg) { msg_t *mp; global_t *global; int done; global = (global_t *)arg; done = 0; while (done < SIZE) { pthread_mutex_lock(&global->qlock); while (global->size < 1) { printf("开始等待##############\n"); pthread_cond_wait(&global->qready, &global->qlock); printf("等待结束##############\n"); } mp = global->workq; global->workq = mp->next; global->size--; pthread_mutex_unlock(&global->qlock); printf("处理%d\n", mp->data); done++; } return (void *)0; } void enqueue_msg(global_t *global, msg_t *mp) { pthread_mutex_lock(&global->qlock); mp->next = global->workq; global->workq = mp; global->size++; pthread_mutex_unlock(&global->qlock); pthread_cond_signal(&global->qready); } void *generate_msg(void *arg) { int i; global_t *global; msg_t *msg; global = (global_t *)arg; for (i = 0; i < SIZE; i++) { msg = malloc(sizeof(msg_t)); msg->data = i; printf("%d入队...\n", i); enqueue_msg(global, msg); printf("%d入队完成...\n", i); } return (void *)0; } int main() { pthread_t ptid, gtid; global_t global; void *tret; global.workq = NULL; global.size = 0; pthread_cond_init(&global.qready, NULL); pthread_mutex_init(&global.qlock, NULL); pthread_create(&ptid, NULL, process_msg, &global); pthread_create(>id, NULL, generate_msg, &global); pthread_join(ptid, &tret); pthread_join(gtid, &tret); return 0; }
上面的例子开启了两个线程分别用来产生和消耗消息,加上main,总共有3个线程在跑,如果把产生消息的工作放到
main函数中,是否依然需要同步呢?当然需要,因为main函数本身也是一个线程,依然要和处理消息的线程保持同步。
代码如下:
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #define SIZE 10000 typedef struct msg_t { int data; struct msg_t *next; } msg_t; typedef struct global_t { msg_t *workq; pthread_cond_t qready; pthread_mutex_t qlock; int size; /* 队列中待处理的消息数量 */ } global_t; void *process_msg(void *arg) { msg_t *mp; global_t *global; int done; global = (global_t *)arg; done = 0; while (done < SIZE) { pthread_mutex_lock(&global->qlock); while (global->size < 1) { printf("开始等待##############\n"); pthread_cond_wait(&global->qready, &global->qlock); printf("等待结束##############\n"); } mp = global->workq; global->workq = mp->next; global->size--; pthread_mutex_unlock(&global->qlock); printf("处理%d\n", mp->data); done++; } return (void *)0; } void enqueue_msg(global_t *global, msg_t *mp) { pthread_mutex_lock(&global->qlock); mp->next = global->workq; global->workq = mp; global->size++; pthread_mutex_unlock(&global->qlock); pthread_cond_signal(&global->qready); } void *generate_msg(void *arg) { int i; global_t *global; msg_t *msg; global = (global_t *)arg; for (i = 0; i < SIZE; i++) { msg = malloc(sizeof(msg_t)); msg->data = i; printf("%d入队...\n", i); enqueue_msg(global, msg); printf("%d入队完成...\n", i); } return (void *)0; } int main() { pthread_t ptid, gtid; global_t global; void *tret; global.workq = NULL; global.size = 0; pthread_cond_init(&global.qready, NULL); pthread_mutex_init(&global.qlock, NULL); pthread_create(&ptid, NULL, process_msg, &global); generate_msg(&global); /* 把产生消息的工作放到main函数中 */ pthread_join(ptid, &tret); return 0; }
4 信号量 semaphore
mutex变量是非0即1的,可看作一种资源的可用数量,初始化时mutex是1,表示有一个可用资源,加锁
时获得该资源,将mutex减到0,表示不再有可用资源,解锁时释放该资源,将mutex重新加到1,表示又有了
一个可用资源。信号量(semaphore)和mutex类似,表示可用资源的数量,和mutex不同的是这个数量可以大于1。
这种信号量不仅可用于同一进程的线程间同步,也可用于不同进程间的同步。
linux中提供的接口为:
#include <semaphore.h> 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_post(sem_t * sem); int sem_destroy(sem_t * sem);
semaphore变量的类型为sem_t,sem_init()初始化一个semaphore变量,value参数表示可用资源的数量,
pshared参数为0表示信号量用于同一进程的线程间同步。在用完semaphore变量之后应该
调用sem_destroy()释放与semaphore相关的资源。
调用sem_wait()可以获得资源,使semaphore的值减1,如果调用sem_wait()时semaphore的值已经是0,
则挂起等待。如果不希望挂起等待,可以调用sem_trywait()。调用sem_post()可以释放资源,
使semaphore的值加1,同时唤醒挂起等待的线程。
semaphore实例:生产者和消费者问题
#include <stdlib.h> #include <pthread.h> #include <stdio.h> #include <semaphore.h> #define NUM 5 int queue[NUM]; sem_t blank_number, product_number; void *producer(void *arg) { int p = 0; while (1) { sem_wait(&blank_number); queue[p] = rand() % 1000 + 1; printf("Produce %d\n", queue[p]); sem_post(&product_number); p = (p+1)%NUM; sleep(rand()%5); } } void *consumer(void *arg) { int c = 0; while (1) { sem_wait(&product_number); printf("Consume %d\n", queue[c]); queue[c] = 0; sem_post(&blank_number); c = (c+1)%NUM; sleep(rand()%5); } } int main(int argc, char *argv[]) { pthread_t pid, cid; sem_init(&blank_number, 0, NUM); sem_init(&product_number, 0, 0); pthread_create(&pid, NULL, producer, NULL); pthread_create(&cid, NULL, consumer, NULL); pthread_join(pid, NULL); pthread_join(cid, NULL); sem_destroy(&blank_number); sem_destroy(&product_number); return 0; }
发表评论
-
Virtualbox下Windows和Linux实现文件互传
2012-07-17 21:05 33831 Windows安装好Linux虚拟机 2 在Lin ... -
Memcached源码分析之网络模型篇
2012-03-02 01:46 4141memcached 采用多线程的工作方式, 主线程接收连接, ... -
Memcached源码分析之内存管理篇
2012-02-26 15:04 12076使用命令 set(key, value) ... -
多线程与volatile变量
2012-02-25 17:07 5426volatile 修饰的变量表示改变量的值是易变的,编译 ... -
items
2011-11-12 19:30 71 上肢长 2 上臂长 ... -
fds
2011-11-12 19:23 10身高(静态) 眼高 ... -
xml
2011-11-12 18:58 7<item idx = "1" ... -
fff
2011-11-12 18:30 8上肢长 上臂长 两下颌角宽 两眼内宽 两耳屏点间 ... -
(转) memcached采用的网络模型
2011-10-12 01:58 12memcached采用的网络模型 ... -
Nginx 内存池
2011-10-12 01:46 7nginx的内存管理,主要是用来实现防止内存泄露,和内存碎片, ... -
Nginx负载均衡
2011-10-12 01:40 10nginx的upstream目前支持5种方式的分配 ... -
守护进程的实现
2011-09-30 01:43 18466个步骤 步骤1:创建子进程,杀死父进程,目的是为了步 ... -
非阻塞connect的实现
2011-09-30 01:12 14789步骤1: 设置非阻塞,启动连接 实现非阻塞 connect ... -
Memcached内存管理机制
2011-09-29 20:57 2358Slab 分配机制 Memcache ... -
关于大端法和小端法
2011-09-28 23:15 2353typedef union { int n; ... -
vim配置文件精简版
2011-09-19 09:37 1949"Get out of VI's compatibl ... -
(转) Linux 的僵尸(zombie)进程
2011-09-17 20:29 3190原文地址: http://cool ... -
Linux信号详解
2011-09-17 01:02 36354一 信号的种类 可靠信号与不可靠信号, 实时信号与非实时信号 ... -
消息队列
2011-09-15 22:16 12240一 应用场景 有很多业务, 客户端和内网都要进行数据传 ... -
vim + taglist + ctags + cscope 简单使用
2011-09-08 21:58 3560ctags用来跳转, taglist用来列出当前文件的变量, ...
相关推荐
5. **pthread_cond_wait()** 和 **pthread_cond_signal()**:条件变量的等待和信号操作,用于实现更复杂的线程同步策略。 #### pthread的高级特性 - **线程优先级与调度策略**:可以通过设置线程属性来调整线程的...
Linux下的pthread线程库是实现多线程编程的关键工具,遵循POSIX标准,提供了一整套接口用于创建、管理线程以及同步线程间的操作。本文将深入探讨pthread线程库,包括线程的创建与结束、线程绑定、线程状态、线程...
在pthread线程库中,"锁的技巧"是一个重要的概念。锁是用来控制多个线程对共享资源访问的一种机制,以避免数据竞争和不一致性的发生。主要的锁类型包括: 1. 互斥锁(Mutex):互斥锁确保任何时候只有一个线程能...
**Pthread线程包在Windows平台的移植与应用** Pthread,全称为POSIX线程,是UNIX系统标准的一部分,提供了跨平台的多线程编程接口。它在Linux和其他符合POSIX标准的操作系统中广泛使用,允许开发者创建并管理多个...
同时,了解线程同步和通信机制有助于预防和解决常见的并发问题,如死锁、饥饿和活锁。总之,《Pthread多线程编程指南》是提升多线程编程技能的宝贵资源,值得每一位关注性能优化和并发编程的开发者深入研究。
总结来说,C++封装`pthread`线程涉及的关键点包括线程创建、线程函数、线程同步和线程管理。通过理解这些概念并结合实际应用,开发者可以在Linux环境中有效地利用多线程技术提高程序的并发性能。在实际项目中,还...
2. **线程同步**:在多线程环境中,数据一致性是个关键问题。`pthread_join()`函数用于等待特定线程的完成,确保线程间的正确顺序。另外,互斥锁(`pthread_mutex_t`)可用于保护共享资源,防止数据竞争。 3. **...
在实际应用中,还需要考虑线程安全、资源竞争、死锁等问题,以及如何正确地使用互斥锁`pthread_mutex_t`等同步工具来保护共享数据。多线程编程是一个复杂但强大的技术,能够帮助我们构建出更加灵活和高性能的应用...
总结,"Jni多线程同步事例"着重展示了如何在JNI中应用线程同步技术解决生产者-消费者问题。理解并掌握这一技术有助于优化多线程Java应用,尤其是当需要调用本地库或实现高性能计算时。在实际项目中,应根据具体需求...
线程同步,指一个线程发出某一功能调用时,在没有得到结果之前,该调用不返回。同时其它线程为保证数据一致性,不能调用该功能。 举例1: 银行存款 5000。柜台,折:取3000;提款机,卡:取 3000。剩余:2000 举例2...
"临界区"和"多线程同步"是解决这一问题的关键概念。临界区是一种同步机制,它允许一次只有一个线程访问特定的代码区域或资源,以避免并发访问时可能产生的数据竞争和不一致性。多线程同步则是为了协调多个线程的执行...
使用pthread库可以编写出高效、并发的多线程程序,但需要注意线程安全问题,比如数据竞争和死锁。合理地使用锁(mutex)、信号量、条件变量等同步机制是至关重要的。同时,了解pthread的线程生命周期管理、线程局部...
2. **多线程同步问题** 当多个Java线程调用同一个本地方法,它们可能同时访问和修改共享资源,这就需要同步控制。在Java中,我们可以使用`synchronized`关键字、`java.util.concurrent`包中的工具类等来实现同步。...
实验内容集中在Linux下的多线程同步机制上,具体通过修改生产者-消费者问题的示例程序来实现。在这个问题中,多个生产者线程生成数据,而消费者线程负责消费这些数据。为了保证数据的一致性和正确性,需要防止多个...
6. **线程同步与通信**:Pthread还提供了各种同步机制,如互斥锁(`pthread_mutex_t`)、条件变量(`pthread_cond_t`)、信号量(`sem_t`)等,用于控制线程间的执行顺序和数据共享安全。 7. **资源释放**:当线程...
信号量(Semaphore)在Pthread中通过`semaphore.h`头文件进行操作,主要用于线程间的同步。`sem_init`用于初始化信号量,`sem_wait`会使信号量减一并可能阻塞线程,`sem_post`则使信号量加一,释放资源。`sem_...
6. **哲学家就餐问题**:这是一个经典的线程同步问题,用来说明死锁的可能性。在实验中,你可以通过实现这个例子来理解线程同步的重要性,并学习如何避免死锁。 在"操作系统实验三"中,你可能需要编写代码来模拟...
在计算机科学中,多线程编程是一种允许程序同时执行多个任务的技术。在Unix-like系统,如Linux,`pthread`库是实现多...然而,多线程编程也带来了复杂性和挑战,例如同步问题和资源管理,因此在实践中需要谨慎处理。
pthread 条件变量,线程同步