最近开发基于ZYNQ的嵌入式linux程序,涉及到多线程使用,将一些内容整理如下:

POSIX多线程编程最为基础和重要的可以分为两部分:

  1. 线程操作-Thread Management
  2. 线程同步-Synchronization

线程同步主要是由于线程共享同一进程里的资源,因而需要程序员自己对资源进行同步来避免竞争产生

1.线程操作

pthread_create (thread,attr,start_routine,arg) 

pthread_exit (status)

pthread_cancel (thread)

pthread_attr_init (attr)

pthread_attr_destroy (attr) 

具体函数使用见参考文献1,现将参考文献1中示例代码贴出

/******************************************************************************
* FILE: hello.c
* DESCRIPTION:
* A "hello world" Pthreads program. Demonstrates thread creation and
* termination.
* AUTHOR: Blaise Barney
* LAST REVISED: 08/09/11
******************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 5 void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
} int main(int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=;t<NUM_THREADS;t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-);
}
} /* Last thing that main() should do */
pthread_exit(NULL);
}

2.线程同步

线程同步POSIX主要提供两种结构:

  • 互斥量
  • 条件变量

互斥量的使用较为简单,具体参见参考文献1,现贴出参考文献1中示例代码

 #include <pthread.h>
#include <stdio.h>
#include <stdlib.h> /*
The following structure contains the necessary information
to allow the function "dotprod" to access its input data and
place its output into the structure.
*/ typedef struct
{
double *a;
double *b;
double sum;
int veclen;
} DOTDATA; /* Define globally accessible variables and a mutex */ #define NUMTHRDS 4
#define VECLEN 100
DOTDATA dotstr;
pthread_t callThd[NUMTHRDS];
pthread_mutex_t mutexsum; /*
The function dotprod is activated when the thread is created.
All input to this routine is obtained from a structure
of type DOTDATA and all output from this function is written into
this structure. The benefit of this approach is apparent for the
multi-threaded program: when a thread is created we pass a single
argument to the activated function - typically this argument
is a thread number. All the other information required by the
function is accessed from the globally accessible structure.
*/ void *dotprod(void *arg)
{ /* Define and use local variables for convenience */ int i, start, end, len ;
long offset;
double mysum, *x, *y;
offset = (long)arg; len = dotstr.veclen;
start = offset*len;
end = start + len;
x = dotstr.a;
y = dotstr.b; /*
Perform the dot product and assign result
to the appropriate variable in the structure.
*/ mysum = ;
for (i=start; i<end ; i++)
{
mysum += (x[i] * y[i]);
} /*
Lock a mutex prior to updating the value in the shared
structure, and unlock it upon updating.
*/
pthread_mutex_lock (&mutexsum);
dotstr.sum += mysum;
pthread_mutex_unlock (&mutexsum); pthread_exit((void*) );
} /*
The main program creates threads which do all the work and then
print out result upon completion. Before creating the threads,
the input data is created. Since all threads update a shared structure,
we need a mutex for mutual exclusion. The main thread needs to wait for
all threads to complete, it waits for each one of the threads. We specify
a thread attribute value that allow the main thread to join with the
threads it creates. Note also that we free up handles when they are
no longer needed.
*/ int main (int argc, char *argv[])
{
long i;
double *a, *b;
void *status;
pthread_attr_t attr; /* Assign storage and initialize values */
a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double)); for (i=; i<VECLEN*NUMTHRDS; i++)
{
a[i]=1.0;
b[i]=a[i];
} dotstr.veclen = VECLEN;
dotstr.a = a;
dotstr.b = b;
dotstr.sum=; pthread_mutex_init(&mutexsum, NULL); /* Create threads to perform the dotproduct */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); for(i=; i<NUMTHRDS; i++)
{
/*
Each thread works on a different set of data. The offset is specified
by 'i'. The size of the data for each thread is indicated by VECLEN.
*/
pthread_create(&callThd[i], &attr, dotprod, (void *)i);
} pthread_attr_destroy(&attr); /* Wait on the other threads */
for(i=; i<NUMTHRDS; i++)
{
pthread_join(callThd[i], &status);
} /* After joining, print out the results and cleanup */
printf ("Sum = %f \n", dotstr.sum);
free (a);
free (b);
pthread_mutex_destroy(&mutexsum);
pthread_exit(NULL);
}

条件变量和互斥量一般同时使用(原因下面做分析),使用方法参见参考文献1,现贴出参考文献1示例代码

/******************************************************************************
* FILE: condvar.c
* DESCRIPTION:
* Example code for using Pthreads condition variables. The main thread
* creates three threads. Two of those threads increment a "count" variable,
* while the third thread watches the value of "count". When "count"
* reaches a predefined limit, the waiting thread is signaled by one of the
* incrementing threads. The waiting thread "awakens" and then modifies
* count. The program continues until the incrementing threads reach
* TCOUNT. The main program prints the final value of count.
* SOURCE: Adapted from example code in "Pthreads Programming", B. Nichols
* et al. O'Reilly and Associates.
* LAST REVISED: 03/07/17 Blaise Barney
******************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h> #define NUM_THREADS 3
#define TCOUNT 10
#define COUNT_LIMIT 12 int count = ;
pthread_mutex_t count_mutex;
pthread_cond_t count_threshold_cv; void *inc_count(void *t)
{
int i;
long my_id = (long)t; for (i=; i < TCOUNT; i++) {
pthread_mutex_lock(&count_mutex);
count++; /*
Check the value of count and signal waiting thread when condition is
reached. Note that this occurs while mutex is locked.
*/
if (count == COUNT_LIMIT) {
printf("inc_count(): thread %ld, count = %d Threshold reached. ",
my_id, count);
pthread_cond_signal(&count_threshold_cv);
printf("Just sent signal.\n");
}
printf("inc_count(): thread %ld, count = %d, unlocking mutex\n",
my_id, count);
pthread_mutex_unlock(&count_mutex); /* Do some work so threads can alternate on mutex lock */
sleep();
}
pthread_exit(NULL);
} void *watch_count(void *t)
{
long my_id = (long)t; printf("Starting watch_count(): thread %ld\n", my_id); /*
Lock mutex and wait for signal. Note that the pthread_cond_wait routine
will automatically and atomically unlock mutex while it waits.
Also, note that if COUNT_LIMIT is reached before this routine is run by
the waiting thread, the loop will be skipped to prevent pthread_cond_wait
from never returning.
*/
pthread_mutex_lock(&count_mutex);
while (count < COUNT_LIMIT) {
printf("watch_count(): thread %ld Count= %d. Going into wait...\n", my_id,count);
pthread_cond_wait(&count_threshold_cv, &count_mutex);
printf("watch_count(): thread %ld Condition signal received. Count= %d\n", my_id,count);
}
printf("watch_count(): thread %ld Updating the value of count...\n", my_id);
count += ;
printf("watch_count(): thread %ld count now = %d.\n", my_id, count);
printf("watch_count(): thread %ld Unlocking mutex.\n", my_id);
pthread_mutex_unlock(&count_mutex);
pthread_exit(NULL);
} int main(int argc, char *argv[])
{
int i, rc;
long t1=, t2=, t3=;
pthread_t threads[];
pthread_attr_t attr; /* Initialize mutex and condition variable objects */
pthread_mutex_init(&count_mutex, NULL);
pthread_cond_init (&count_threshold_cv, NULL); /* For portability, explicitly create threads in a joinable state */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&threads[], &attr, watch_count, (void *)t1);
pthread_create(&threads[], &attr, inc_count, (void *)t2);
pthread_create(&threads[], &attr, inc_count, (void *)t3); /* Wait for all threads to complete */
for (i = ; i < NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
printf ("Main(): Waited and joined with %d threads. Final value of count = %d. Done.\n",
NUM_THREADS, count); /* Clean up and exit */
pthread_attr_destroy(&attr);
pthread_mutex_destroy(&count_mutex);
pthread_cond_destroy(&count_threshold_cv);
pthread_exit (NULL); }

初次接触条件变量很容易疑惑为什么条件变量一定要与互斥量一同使用,很多人认为互斥量是用来保证条件变量的原子性的,其实这是没有真正理解条件变量设计初衷导致的。

条件变量设计也是为了各个线程同步数据,并非单单做等待。如果不使用条件变量,程序就需要在代码关键区内不断进行查询操作,浪费CPU时间片,为此设计了条件变量来消除查询操作的代价。因此把条件变量看做互斥量的一个补充就好理解为什么两者要同时出现了,而不是把互斥量看做条件变量的补充。

也可以理解为线程数据同步都是靠互斥量进行的,条件变量只是做了一个消息通知机制而已。如果仅仅为了等待,而不存在数据保护,条件变量其实无需互斥量。

参考文献2也做了深入分析,可作参考

参考文献:

1.https://computing.llnl.gov/tutorials/pthreads/

2.http://www.cnblogs.com/Dahaka/archive/2012/02/19/2358528.html

POSIX 多线程编程及理解的更多相关文章

  1. [posix]Posix多线程编程

    就不排版了,可以到原作者博客下看 转自:http://www.cnblogs.com/zhangsf/archive/2013/09/09/3309867.html 目录表  摘要 译者序 Pthre ...

  2. POSIX多线程编程(上)-基本概念

    线程概念 我们把正在计算机中执行的程序叫做"进程"(Process) ,而不将其称为程序(Program).所谓"线程"(Thread),是"进程&q ...

  3. Posix多线程编程学习笔记

    Blaise Barney, Lawrence Livermore National Laboratory )标准制订了这一标准接口.依赖于该标准的实现就称为POSIX threads 或者Pthre ...

  4. POSIX多线程编程-条件变量pthread_cond_t

    条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其它 ...

  5. Linux多线程编程(不限Linux)【转】

    ——本文一个例子展开,介绍Linux下面线程的操作.多线程的同步和互斥. 前言 线程?为什么有了进程还需要线程呢,他们有什么区别?使用线程有什么优势呢?还有多线程编程的一些细节问题,如线程之间怎样同步 ...

  6. Linux多线程编程(不限Linux)

    前言 线程?为什么有了进程还需要线程呢,他们有什么区别?使用线程有什么优势呢?还有多线程编程的一些细节问题,如线程之间怎样同步.互斥,这些东西将在本文中介绍.我在某QQ群里见到这样一道面试题: 是否熟 ...

  7. Linux多线程编程(不限Linux)转

    ——本文一个例子展开,介绍Linux下面线程的操作.多线程的同步和互斥. 前言 线程?为什么有了进程还需要线程呢,他们有什么区别?使用线程有什么优势呢?还有多线程编程的一些细节问题,如线程之间怎样同步 ...

  8. Linux多线程编程之详细分析

    线程?为什么有了进程还需要线程呢,他们有什么区别?使用线程有什么优势呢?还有多线程编程的一些细节问题,如线程之间怎样同步.互斥,这些东西将在本文中介绍.我见到这样一道面试题: 是否熟悉POSIX多线程 ...

  9. Linux多线程编程,为什么要使用线程,使用线程的理由和优点等

    线程?为什么有了进程还需要线程呢,他们有什么区别?使用线程有什么优势呢?还有多线程编程的一些细节问题,(http://www.0830120.com)如线程之间怎样同步.互斥,这些东西将在本文中介绍. ...

随机推荐

  1. Onvif开发之客户端搜索篇

    关于ONVIF的广播,有客户端搜索和服务端发现的区别:客户端向固定的网段和固定的端口发送广播消息,服务端在对应的端口回复广播请求消息本文首先介绍客户端如何进行广播的已经对广播回复的信息的基本处理. 客 ...

  2. 58.express安装问题:express不是内部也或者外部的命令解决方案

    转自:https://www.cnblogs.com/zhangym118/p/5842094.html "Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列 ...

  3. 30.IntellJ Idea 导入已存在的Maven项目

    转自:https://blog.csdn.net/epdc2/article/details/53767386

  4. 闲的无聊写了个很(wu)有(liao)意(dao)思(bao)的程序

    下午机房断网了 闲的无聊,写了个小游戏 忘了sleep在哪个库里了.. 自带变色效果哦 #include<iostream> #include<cstdio> #include ...

  5. vue 中表单 [v-bind:true-value="a" v-bind:false-value="b"] 的用法

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 2018 java实训总结(时间戳&&主键)

    java实训题目:源管理系统. 答辩的时候被老师怼了以下几个的地方: 1.主键改变了 2.没时间戳却说自己的程序里有先后(这就是老师迂腐了,主键自增可以间接反馈出他加入的早晚,即使主键做出了改变但只是 ...

  7. [分享]ip地址爬取过滤的shell

    http://www.hbbzy.me/分享ip地址爬取过滤的shell #!/bin/base #ip zhi地址匹配 #获取最新的ip地址 #author:haifeng #wget ftp:// ...

  8. Android学习笔记进阶十一图片动画播放(AnimationDrawable)

    大家平时见到的最多的可能就是Frame动画了,Android中当然也少不了它.它的使用更加简单,只需要创建一个 AnimationDrawabledF对象来表示Frame动画,然后通过addFrame ...

  9. HASH Partitioning--转载

    原文地址:https://dev.mysql.com/doc/refman/5.1/en/partitioning-hash.html HASH Partitioning [+/-] 18.2.3.1 ...

  10. Code froces 831 A. Unimodal Array

    A. Unimodal Array time limit per test 1 second memory limit per test 256 megabytes input standard in ...