「并行学习」Pthread

又一个新坑QAQ

Shared-Memory Programming

Definition: Processes communicate or work together with each other through a shared memory space which can be accessed by all processes.

在这里插入图片描述

Many issues as well: Synchronization, Deadlock, Cache coherence

Threads vs. Processes

一个Processes可以create出许多Threads。两者最大的差别是:**Thread之间有一部分memory contains是共用的,还有一部分是不共用的。**共用的部分就是Thread可以沟通的原因,而不共用的地方则是每个Thread可以独立执行code的原因。

在这里插入图片描述

名称含义
Process (heavyweight process)complete separate program with its own variables, stack, heap, and everything else.
Thread (lightweight process)share the same memory space for global variables, resources.

这里共用的resource举一个例子:Thread打开一个文件之后,会产生一个handler,其他的Thread也可以使用这个handler去执行程式,这就是resource的共用。

In Linux, Threads are created via clone a process with a flag to indicate the level of sharing.

也就是说,如果一个一个新的Thread与之前的process完全不共享内存,它就是一个新的process。

为什么使用Thread

  1. Lower creation/management cost vs. Process.

  2. Faster inter-process communication vs. MPI.(如果程式跑在一台电脑里,MPI速度就没有Pthread好了)

Pthread

什么是Pthread

POSIX (Potable Operating System Interface) standard is specified for portability across Unix-like systems.

Pthread is the implementation of POSIX standard for thread.

这里,thread中执行的程式不一定是一样的

Pthread Creation

pthread_create(thread,attr,routine,arg)
/**
**********
thread: An unique identifier (token) for the new thread.main thread通过这个token与新创建的thread沟通。
attr: It is used to set thread attributes. NULL for the default values.
routine: The routine that the thread will execute once it is created.
arg: A single argument that may be passed to routine.
**********
**/

使用pthread_create()来创建一个新的thread,新的thread执行routine指向的function call就可以。新创建的thread与之前的thread之间就可以被OS查询到,于是就可以在不同的core上执行。

在这里插入图片描述

#include <pthread.h>
#include <stdio.h> #define NUM_THREADS 5
void *PrintHello(void *threadId) {
long* data = static_cast <long*> threadId; printf("Hello World! It's me, thread #%ld!\n", *data);
pthread_exit(NULL); }
int main (int argc, char *argv[]) {
pthread_t threads[NUM_THREADS];
for(long tid=0; tid<NUM_THREADS; tid++){
} pthread_create(&threads[tid], NULL, PrintHello, (void *)&tid);
/* Last thing that main() should do */
pthread_exit(NULL); }

从上例中可以看到:

  1. 传递的参数arg,实际上传递的是一个void类型的指针,在传递之后通过强制类型转换转换成原来的类型。

  2. 如果不给主进程回传消息的时候,可以使用phtread_exit(NULL);命令。

Pthread Joining & Detaching

一个线程最后会被 detach 或者被 join 。

pthread_join(threadId, status)
/**
**********
Blocks until the specified threadId thread terminates
One way to accomplish synchronization between threads
Example: to create a pthread barrier
for (int i=0; i<n; i++) pthread_join(thread[i], NULL);
**********
**/

pthread_join()的作用是让call join的那个function block在pthread_join(),直到threadId对应的thread结束,才能继续。通常,这是为了取回status中的值,但这也是一种实现同步的方式

在这里插入图片描述

pthread_detach(threadId)
/**
**********
Once a thread is detached, it can never be joined 
Detach a thread could free some system resources
**********
**/

pthread_detach(threadId)的作用是将thread合并,但是不需要被合并的thread中的返回值或者被合并的thread中本身就没有返回值。比如,在web server中,每监听到一个request,就会创建一个新的thread,但main thread并不关心创建的thread执行了什么,因此也就不需要返回值。

Synchronization Problem & Tools

Synchronization Problem

The outcome of data content should NOT be decided by the execution order among processes.

Critical Section & Mutual Exclusion

  1. Critical Section is a piece of code that can only be accessed by one process/thread at a time

  2. Mutual exclusion is the problem to insure only one process/thread can be in a critical section

在这里插入图片描述

Locks

the simplest mechanism for ensuring mutual exclusion of critical section。

在Pthread里,Lock是mutex,代表mutual exclusion

原理:

while (lock == 1);
lock = 1;
/**
	...
	critical section 
	...
**/
lock = 0;
/* no operation in while loop */ /* enter critical section */
/* leave critical section */

Pthread Lock/Mutex Routines

#include “pthread.h” 
pthread_mutex_t mutex; 
//mutex并不是一个简单的lock,而是一个结构体,因此需要init
pthread_mutex_init(&mutex, NULL); 
pthread_mutex_lock(&mutex);
/**
	...
	Critical Section
	...
**/
pthread_mutex_unlock(&mutex); 
pthread_mutex_destroy(&mutex);

mutex一定要是个global variable,因为不同的thread都要访问mutex,从而实现同步。

Counded-Buffer Problem

Producer process produces information that is consumed by a Consumer process

Parbegin
     Producer:  begin
		repeat
		   /**
		    produce an item in nextp;
		    **/
		 	P(empty);
		  P(mutex);
		  add nextp to buffer;
		  V(mutex);
		  V(full);
		 until false;
	   end;
			consumer:begin
	    repeat
	       P(full);
	       P(mutex);
	       remove an item from buffer to nextc
	       释放缓冲区
	       V(mutex);
	       V(empty);
			/**
			 consume the item in nextc;
			**/
		      until false;
		  end;
           Parend;

Condition Variables (CV)

CV represent some condition that a thread can:

  1. Wait on, until the condition occurs;
  2. Notify other waiting threads that the condition has occurred .

Three operations on condition variables:

在Pthread中,CV的类型是pthread_cond_t

函数作用
pthread_cond_wait(&theCV,&someLock)Block until another thread calls signal() or broadcast() on the CV
pthread_cond_signal(&theCV)Wake up one thread waiting on the CV
pthread_cond_broadcast(&theCV)Wake up all threads waiting on the CV

只有在critical section中,才能使用CV。

Using Condition Variable

/*
**********
Example:
	A threads is designed to take action when x=0
	Another thread is responsible for decrementing(递减) the counter
**********
*/

/*定义*/
pthread_cond_t cond;
pthread_mutex_t mutex;
pthread_cond_init (cond, NULL); 
pthread_mutex_init (mutex, NULL);

/*实现*/
action() {
	pthread_mutex_lock (&mutex);
	if (x != 0)
		pthread_cond_wait (cond, mutex);
	pthread_mutex_unlock (&mutex);
	take_action(); 
}


counter() {
	pthread_mutex_lock (&mutex);
	x--;
	if (x==0)
		pthread_cond_signal (cond);
  pthread_mutex_unlock (&mutex);
} 

All condition variable operation MUST be performed while a mutex is locked! But why is the lock necessary?

Because event counter “x” is a SHARED variable

  1. If no lock on thread action()…
    Wait after any thread (i.e. not counter) sets “x” to 0
  2. If no lock on thread counter()…
    No guarantee that decrement and test of “x” is atomic
  3. Requiring CV operations to be done while holding a lock
    prevents a lot of common programming mistakes

Semaphore

A tool to generalize the synchronization problem

在这里插入图片描述

有两个不同的操作:wait & signal

POSIX Semaphore

Semaphore is part of POSIX standard BUT it is not belonged to Pthread.

sem_init(sem_t *sem, int pshared, unsigned int value);
sem_wait(sem_t *sem);
sem_post(sem_t *sem);
sem_getvalue(sem_t *sem, int *valptr);
sem_destory(sem_t *sem);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值