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 ...
随机推荐
- 基于H5的移动端开发,window.location.href在IOS系统无法触发问题
最近负责公司的微信公众号开发项目,基于H5进行开发,某些页面window.location.href在Android机上能正常运行而IOS系统上无法运行,导致无法重定向到指定页面,查了好久终于找到方法 ...
- eap-ttls/mschapv2
eap-ttls/mschapv2 文件路径 用途 示例 备注 #gedit /usr/local/etc/raddb/sites-available/default #gedit /us ...
- tesseract 编译与使用(windows)
tesseract是google的一个开源OCR项目,项目地址已经迁移到github(现在 2016/09),地址 https://github.com/tesseract-ocr/tesseract ...
- x.1
最近公司人事变动略频 昨日老板召集众骨干动员,谈心,表示有信心,没资金压力. 今日各种谈心,唉…… 人事姐姐约逻辑组长聊,美术主管就找上了我,一通倾述.内容实事求是,但是行业内各公司都这样,唉,还想着 ...
- restful
根据名称对应 相当于换了别名(很无聊)
- j2ee学习资料收集
1 tomcat web.xml加载顺序, 讲解了web.xml什么时候加载,内部的各个组件加载的顺序 http://blog.sina.com.cn/s/blog_4553489c01010 ...
- PKU1008
题名:玛雅历 题意:历法转换 . 代码: // 1008.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iost ...
- 字符数组和string判断是否为空行 NULL和0 namespace变量需要自己进行初始化
string 可以这样判断空行input !="" 字符数组可以通过判断第一个元素是否为空字符'\0',是的话为空行arrar[0]=='\0':或者用长度strlen(char ...
- 20145210 20145226 《信息安全系统设计基础》实验五 简单嵌入式WEB服务器实验
20145210 20145226 <信息安全系统设计基础>实验五 简单嵌入式WEB服务器实验 结对伙伴:20145226 夏艺华 实验报告封面 实验目的与要求 · 掌握在ARM开发板实现 ...
- 如何开发、调试Hybrid项目-- 入门篇
前言 随着移动浪潮的兴起,各种APP层出不穷,极速的业务扩展提升了团队对开发效率的要求,这个时候使用IOS&Andriod开发一个APP似乎成本有点过高了,而H5的低成本.高效率.跨平台等特性 ...