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 ...
随机推荐
- 使用 VS2005 通过按钮自动上传文件到Linux
首先去官网下载 winscp,官网地址:http://winscp.net/eng/download.php 因为我这里是做自动上传工具,所以我只下载了精简版的:Portable executable ...
- hihoCoder#1135
刚开始学习C语言,准备在做hiho的题目的过程中来学习,在此进行记录,如果代码中有错误或者不当的地方还请指正. 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 The c ...
- python 中的高级函数map()
map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回. 例如,对于list [1, 2 ...
- linux -a 到 -z 的意义
shell if判断中常用的也就是绿色部分,尾部部分越看越不懂.从百度文库转载. [ -a FILE ] 如果 FILE 存在则为真. [ -b FILE ] 如果 FILE 存在且是一个块特殊文件则 ...
- C++引用的作用和用法
引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样. 引用的声明方法:类型标识符&引用名=目标变量名: 例如: int q; int &ra=a; 说明: &am ...
- C语言程序设计第四次作业
态度决定一切,我依然要说这句话,每次同学们提交的作业,我都会认真评阅,相比实验课而言,可以有更充足的时间来发现问题,很多同学的代码依然会存在一些语法错误或者考虑不周全的现象,我提出了,那么,你认真看了 ...
- SQL排序
- Win8 安装 Scrapy
安装Python2.7.11 32位(自带pip) 使用如下命令更新pip python -m pip install -U pip 下载lxml,建议32位,直接安装 https://pypi.py ...
- js 正则表达式 转至(七郎's Blog)
//匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线 var re =new RegExp("^[a-zA-Z][a-zA-Z0-9_]{5,19}$"); if( ...
- Velocity快速入门教程-脚本语法详解(转)
1.变量 (1)变量的定义: #set($name = "hello") 说明:velocity中变量是弱类型的. 当使用#set 指令时,括在双引号中的字面字符串将解析 ...