Linux Pthread 深入解析(转-度娘818)
Linux Pthread 深入解析
Outline
- 1.线程特点
- 2.pthread创建
- 3.pthread终止
- 4.mutex互斥量使用框架
- 5.cond条件变量
- 6.综合实例
1. 线程特点
pthread_cond_destroy
- while (1) {
- lock(lock_for_X);
- if (X is not empty) {
- unlock(lock_for_X);
- break;
- } else { //X is empty, loop continues
- unlock(lock_for_X);
- sleep(10);
- }
- }
- //X is not empty, loop ends
- process(X);
- while (1) {
- lock(lock_for_X);
- if (X is not empty) {
- unlock(lock_for_X);
- break;
- } else {
- unlock(lock_for_X); //must called before my_wait(), otherwise no one can acquire the lock and make change to X
- -------------------------------------->窗口,由于已经解锁,其他程序可能改变X,并且试图唤醒mywait,但在一个繁忙的系统中,可能此时my_还没被调用!
- my_wait(); //go to sleep and wait for the notification
- }
- }
- lock(lock_for_X);
- while (X is empty) {
- pthread_cond_wait(&qready, &lock_for_X);
- }
- unlock(lock_for_X);
- while(1) {
- lock(lock_for_X);
- dequeue(X);
- unlock(lock_for_X);
- }
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h> static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; struct node
{
int n_number;
struct node *n_next;
} *head = NULL; /*[thread_func]*/ /*释放节点内存 */
static void cleanup_handler(void *arg)
{
printf("Cleanup handler of second thread.\n");
free(arg);
(void)pthread_mutex_unlock(&mtx);
} static void *thread_func(void *arg)
{
struct node *p = NULL;
pthread_cleanup_push(cleanup_handler, p); while ()
{
pthread_mutex_lock(&mtx);
//这个mutex_lock主要是用来保护wait等待临界时期的情况,
//当在wait为放入队列时,这时,已经存在Head条件等待激活
//的条件,此时可能会漏掉这种处理
//这个while要特别说明一下,单个pthread_cond_wait功能很完善,
//为何这里要有一个while (head == NULL)呢?因为pthread_cond_wait
//里的线程可能会被意外唤醒,如果这个时候head != NULL,
//则不是我们想要的情况。这个时候,
//应该让线程继续进入pthread_cond_wait while (head != NULL)
{
pthread_cond_wait(&cond, &mtx);
// pthread_cond_wait会先解除之前的pthread_mutex_lock锁定的mtx,
//然后阻塞在等待队列里休眠,直到再次被唤醒
//(大多数情况下是等待的条件成立而被唤醒,唤醒后,
//该进程会先锁定先pthread_mutex_lock(&mtx);,
// 再读取资源 用这个流程是比较清楚的
/*block-->unlock-->wait() return-->lock*/ p = head;
head = head->n_next;
printf("Got %d from front of queue\n", p->n_number);
free(p);
}
pthread_mutex_unlock(&mtx); //临界区数据操作完毕,释放互斥锁 } pthread_cleanup_pop();
return ;
} int main(void)
{
pthread_t tid;
int i;
struct node *p;
pthread_create(&tid, NULL, thread_func, NULL);
//子线程会一直等待资源,类似生产者和消费者,
//但是这里的消费者可以是多个消费者,
//而不仅仅支持普通的单个消费者,这个模型虽然简单,
//但是很强大
for (i = ; i < ; i++)
{
p = (struct node *)malloc(sizeof(struct node));
p->n_number = i;
pthread_mutex_lock(&mtx); //需要操作head这个临界资源,先加锁,
p->n_next = head;
head = p;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mtx); //解锁
sleep();
}
printf("thread 1 wanna end the cancel thread 2.\n");
pthread_cancel(tid);
//关于pthread_cancel,有一点额外的说明,它是从外部终止子线程,
//子线程会在最近的取消点,退出线程,而在我们的代码里,最近的
//取消点肯定就是pthread_cond_wait()了。
pthread_join(tid, NULL);
printf("All done -- exiting\n");
return ;
}
- /*
- * =====================================================================================
- *
- * Filename: pthread.c
- *
- * Description:
- *
- * Version: 1.0
- * Created: 08/17/11 11:06:35
- * Revision: none
- * Compiler: gcc
- *
- * Author: YOUR NAME (),
- * Company:
- *
- * =====================================================================================
- */
- #include <stdio.h>
- #include <pthread.h>
- #include <error.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- pthread_cond_t qready;
- pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;
- struct foo {
- int cnt;
- pthread_mutex_t f_lock;
- };
- void cleanup(void *arg)
- {
- printf("clean up: %s\n", (char *)arg);
- }
- void printids(char *str)
- {
- printf("%s pid = %u tid = %u / 0x%x\n",
- str, (unsigned int)getpid(), (unsigned int)pthread_self(), (unsigned int)pthread_self());
- }
- void *thread1(void *arg)
- {
- pthread_mutex_lock(&qlock);
- pthread_cond_wait(&qready, &qlock);
- pthread_mutex_unlock(&qlock);
- printids("thread1:");
- pthread_cleanup_push(cleanup, "thread 1 first cleanup handler");
- pthread_cleanup_push(cleanup, "thread 1 second cleanup handler");
- printf("thread 1 push complete!\n");
- pthread_mutex_lock(&((struct foo *)arg)->f_lock);
- ((struct foo *)arg)->cnt;
- printf("thread1: cnt = %d\n", ((struct foo *)arg)->cnt);
- pthread_mutex_unlock(&((struct foo *)arg)->f_lock);
- if (arg)
- return ((void *)0);
- pthread_cleanup_pop(0);
- pthread_cleanup_pop(0);
- pthread_exit((void *)1);
- }
- void *thread2(void *arg)
- {
- int exit_code = -1;
- printids("thread2:");
- printf("Now unlock thread1\n");
- pthread_mutex_lock(&qlock);
- pthread_mutex_unlock(&qlock);
- pthread_cond_signal(&qready);
- printf("Thread1 unlocked\n");
- pthread_cleanup_push(cleanup, "thread 2 first cleanup handler");
- pthread_cleanup_push(cleanup, "thread 2 second cleanup handler");
- printf("thread 2 push complete!\n");
- if (arg)
- pthread_exit((void *)exit_code);
- pthread_cleanup_pop(0);
- pthread_cleanup_pop(0);
- pthread_exit((void *)exit_code);
- }
- int main(int argc, char *argv[])
- {
- int ret;
- pthread_t tid1, tid2;
- void *retval;
- struct foo *fp;
- ret = pthread_cond_init(&qready, NULL);
- if (ret != 0) {
- printf("pthread_cond_init error: %s\n", strerror(ret));
- return -1;
- }
- if ((fp = malloc(sizeof(struct foo))) == NULL) {
- printf("malloc failed!\n");
- return -1;
- }
- if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {
- free(fp);
- printf("init mutex failed!\n");
- }
- pthread_mutex_lock(&fp->f_lock);
- ret = pthread_create(&tid1, NULL, thread1, (void *)fp);
- if (ret != 0) {
- printf("main thread error: %s\n", strerror(ret));
- return -1;
- }
- ret = pthread_create(&tid2, NULL, thread2, (void *)1);
- if (ret != 0) {
- printf("main thread error: %s\n", strerror(ret));
- return -1;
- }
- ret = pthread_join(tid2, &retval);
- if (ret != 0) {
- printf("pthread join falied!\n");
- return -1;
- }
- else
- printf("thread2 exit code %d\n", (int)retval);
- fp->cnt = 1;
- printf("main thread: cnt = %d\n",fp->cnt);
- pthread_mutex_unlock(&fp->f_lock);
- sleep(1); //there is no guarantee the main thread will run before the newly created thread, so we wait for a while
- printids("main thread:");
- printf("Press <RETURN> to exit\n");
- ret = pthread_cond_destroy(&qready);
- if (ret != 0) {
- printf("pthread_cond_destroy error: %s\n", strerror(ret));
- return -1;
- }
- getchar();
- return 0;
- }
Linux Pthread 深入解析(转-度娘818)的更多相关文章
- Linux下得到毫秒级时间--C语言实现(转-度娘818)
Linux下得到毫秒级时间--C语言实现 原文链接: http://www.cnblogs.com/nwf5d/archive/2011/06/03/2071247.html #ifdef HAVE_ ...
- Android 2.3.5源码 更新至android 4.4,能够下载,度娘网盘
Android 4.4源代码下载(linux合并) ==============================切割线结束========================= 旧版本号的能够使用115, ...
- 度娘果然毫无节操,纯粹就是order by 广告费 desc
度娘果然毫无节操,纯粹就是order by 广告费 desc 必应搜索出来排第一,度娘根本就找不到在哪....
- linux mknod命令解析
linux mknod命令解析 http://www.cnblogs.com/cobbliu/archive/2011/07/05/2389014.html mknod:make node 生成设备 ...
- Linux Command Line 解析
Linux Command Line 解析 0 处理模型 Linux kernel的启动包括很多组件的初始化和相关配置,这些配置参数一般是通过command line进行配置的.在进行后续分析之前,先 ...
- Linux 网络配置文件解析
Linux 网络配置文件解析 网络配置文件路径/etc/sysconfig/network-scripts/ifcfg-* *代表网卡名 vim /etc/sysconfig/network- ...
- LINUX DNS客户端 解析域名慢的问题。
Linux系统下域名解析的配置文件是/etc/resolv.conf cat /etc/resolv.conf # Generated by NetworkManager options single ...
- linux log日志解析
linux log日志解析 其实,可以说成是监控系统的记录,系统一举一动基本会记录下来.这样由于信息非常全面很重要,通常只有 root 可以进行视察!通过登录文件(日志文件)可以根据屏幕上面的错误 ...
- Linux服务器配置DNS解析
概述 DNS(Domain Name System,域名系统) DNS的作用,简单的说:就是把我们输入的网站域名翻译成IP地址的系统. 本文建立在已搭建好DNS服务器,这里讨论为linux机器配置DN ...
随机推荐
- EF升级6.0数据库链接不上问题
昨天搞了个mvc4 先从net4.0 升级4.5后 数据库连接不上了, 然后升级ef未最新的6.1 居然还报错 不到方法:“System.Data.Objects.ObjectContext S ...
- could not build module 'XXXXXXXX'或者error: expected identifier or '(' 。一堆奇怪的错误————错误根源
一堆奇怪的错误:1⃣️could not build module 'XXXXXXXX' 2⃣️error: expected identifier or '(' 3⃣️EDIT Setting Pr ...
- 获取 view所在的VC
- (UIViewController*)viewController { for (UIView* next = [self superview]; next; next = next.superv ...
- IOC和Aop使用的扩展
下面还有静态代理和动态代理 1.构造注入 lib包: 在entity包下新建一个实体类User 代码: package cn.happy.entity; public class User { pri ...
- poj3237
//Accepted 2280 KB 688 ms /* source:poj3237 time :2015.5.29 by :songt */ /*题解: 树链剖分 基于边权,路径查询最大值 线段树 ...
- https适配
http://www.jianshu.com/p/f312a84a944c http://www.2cto.com/kf/201611/570823.html http://www.cnblogs.c ...
- 一维码生成 c# winform GUI
最近看到同事小红在做一维码,感觉挺好玩,于是就在网上找了一个例子来玩玩. 下面的代码均为网上的代码,做了一些整理,但是忘记了出处,原作者看到可以提醒我,谢谢. 首先,一维码的相关知识可以先百度一下:h ...
- cocos2dx-3.9 集成admob
Part 1: 安装GoogleMobileAds framework (即admob) 1. 安装Cocoapods,否则解决依赖关系和配置真的会把人不累死也得烦死 sudo gem install ...
- MFC绘图(转载)
http://www.cppblog.com/bestcln/articles/83189.html 1 几何对象的结构和类 为了使用绘图函数,应该先了解绘图所用到的几种表示几何对象的结构和类.这些结 ...
- 关于python函数的学习记录
1.默认参数必须指向不变对象! 2. extra = {'city': 'Beijing', 'job': 'Engineer'}注意kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函 ...