最近开发基于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. 第一个C#控制台程序

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  2. Torch 的安装与基本用法

    本文安装仅限 ubuntu 系统.官方文档见:Getting started with Torch. 0. 简介 Torch 使用轻量级脚本语言 Lua 及其 C/CUDA 扩展模块实现,底层数值计算 ...

  3. centos 6.7下安装rabbitmq 3.6.6过程

    准备,请确保有root权限或者sudo权限,不然不用继续看下去了. 1.erland的安装 首先测试一下是否已经安装了erlang,命令 rpm -qa | grep erlang 若没有安装,则 y ...

  4. Inversion of Control Containers and the Dependency Injection pattern--Martin Fowler

    原文地址:https://martinfowler.com/articles/injection.html n the Java community there's been a rush of li ...

  5. Strtus2学习

    Struts 2 体系结构 : 1.Web浏览器请求一个资源. 2.过滤器Dispatcher查找方法,确定适当的Action. 3.拦截器自动对请求应用通用功能,如验证和文件上传操作. 4.Acti ...

  6. C# 使用 X.509 v.3 证书的方法。

    C# 使用 X.509 v.3 证书的方法. public static void Main()    { // The path to the certificate.        string ...

  7. Dubbo简易学习

    0.  Dubbo简易介绍 DUBBO是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服务提供3,000,000, ...

  8. 如何通过使用fiddler对Android系统设备抓包总结

    http://www.open-open.com/lib/view/open1427509907668.html

  9. 利用JAVA反射机制实现调用私有方法

    1.fragment是AccessibilityFragment的對象.须要被調用的方法的類. setAccessible(true)并非将方法的訪问权限改成了public.而是取消java的权限控制 ...

  10. js22--链式调用

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...