The Linux thread pool implements parallel sorting __linux

Source: Internet
Author: User

In multithreaded programming, if an application needs to create and destroy threads frequently, and the task takes a very short time to execute, then the CPU time is spent creating and destroying the thread. You should use the thread pool at this point. If the thread's creation and thread's destruction are negligible compared to the task's execution time, there is no need to use the thread pool. Let's take a look at a simple implementation:

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include < pthread.h> #include <assert.h> #include <iostream> #define NUM #define THREAD_NUM 3 using namespace std

; int data[num];//to sort the data int thread_unit=10;//each task handles 10 data typedef struct worker{void * (*process) (void *arg);/* The function that the task needs to invoke *
/void *arg;/* The required parameters for this task * * struct worker *next;

} task; /* thread pool structure/typedef struct{PTHREAD_MUTEX_T queue_lock;//thread pool mutually exclusive variable pthread_cond_t queue_ready;//thread pool condition variable task *queue_head ; /* list structure, all waiting task in thread pool/int shutdown;/* destroy thread pool/pthread_t *threadid;//thread id pointer int max_thread_num;/* thread pool number of active threads allowed/int CU

r_queue_size;/* the number of tasks currently waiting for queues */} Thread_pool;
int Add_task (void * (*process) (void *arg), void *arg);

void *thread_routine (void *arg); static Thread_pool *pool = null;//The first pointer is empty void pool_init (int max_thread_num) {pool = (Thread_pool *) malloc (sizeof (thread
	_pool));
	Pthread_mutex_init (& (Pool->queue_lock), NULL); Pthread_conD_init (& (Pool->queue_ready), NULL);
	Pool->queue_head = NULL;
	Pool->max_thread_num = Max_thread_num;
	pool->cur_queue_size = 0;
	Pool->shutdown = 0;
	Pool->threadid = (pthread_t *) malloc (max_thread_num * sizeof (pthread_t));
	int i = 0;
	for (i = 0; i < Max_thread_num; i++) {Pthread_create (& (Pool->threadid[i)), NULL, thread_routine, NULL);//Create Thread } int Add_task (*process) (void *arg), void *arg {* * * Add task to thread pool * * * * * * * * * * * * * * * * * * * * * * * (Task *newworker = (tasks) malloc (Task)
	/* Construct a new task * * newworker->process = process;
	Newworker->arg = arg;
	Newworker->next = NULL;
	Pthread_mutex_lock (& Pool->queue_lock);//Add Task to task queue is mutex to lock task *member = pool->queue_head;
		if (member!= null) {while (Member->next!= null) member = member->next;
	Member->next = Newworker;
	} else{pool->queue_head = newworker;//Tail interpolation} assert (Pool->queue_head!= NULL);
	pool->cur_queue_size++;
	Pthread_mutex_unlock (& (Pool->queue_lock)); PThread_cond_signal (& (Pool->queue_ready));/* Condition has been met, to wait for this condition to signal the thread, wake up the process of hibernation/return 0;
	the int Pool_destroy () {if (Pool->shutdown) return-1;/* prevents two calls */Pool->shutdown = 1;
	/* Wake up all waiting threads, thread pool to destroy/Pthread_cond_broadcast (& (Pool->queue_ready));
	int i; for (i = 0; i < pool->max_thread_num; i++) Pthread_join (Pool->threadid[i], NULL);//All Threads end Free (pool->
	ThreadID);
	/* Destroy wait queue/task *head = NULL;
		while (Pool->queue_head!= NULL) {head = pool->queue_head;
		Pool->queue_head = pool->queue_head->next;
	Free (head);
	}/* Condition variable and mutex also don't forget to destroy/Pthread_mutex_destroy (& (Pool->queue_lock));
	Pthread_cond_destroy (& (Pool->queue_ready));
	Free (pool);
	/* Destroy after the pointer to empty is a good habit of * * pool = NULL;
return 0;
	} void *thread_routine (void *arg) {printf ("Starting thread 0x%x\n", pthread_self ());
		while (1) {Pthread_mutex_lock (& (Pool->queue_lock)); while (pool->cur_queue_size = = 0 &&!pool->shutdown) {/* is in a blocking state if the wait queue is 0 and does not destroy the thread pool; note Pthread_cOnd_wait is an atomic operation, will unlock before waiting, wake up will be added lock/printf ("Thread 0x%x is waiting\n", pthread_self ()); Pthread_cond_wait (& (Pool->queue_ready), & (Pool->queue_lock)),//thread waiting state, unlocking}/* thread pool to destroy */if (pool-&
			Gt;shutdown) {* * encountered Break,continue,return and other jump statements, do not forget to unlock the first * * * * Pthread_mutex_unlock (& (Pool->queue_lock));
			printf ("Thread 0x%x'll exit\n", pthread_self ());
		Pthread_exit (NULL);
		printf ("Thread 0x%x is starting to work\n", pthread_self ()); ASSERT (pool->cur_queue_size!= 0);//task queue is not null assert (Pool->queue_head!= NULL);///* Wait Queue Length minus 1, and remove the header element from the list * * pool-
		>cur_queue_size--;
		Task *worker = pool->queue_head;
		Pool->queue_head = worker->next;
		Pthread_mutex_unlock (& (Pool->queue_lock)); (* (worker->process))
		(WORKER-&GT;ARG); * Call the sort function function to start the task/free (worker);
		worker = NULL;
	Sleep (1); } cout<< "Excute here!"
	<<endl;
Pthread_exit (NULL);
	} void Heapsort (int begin) {//to sort each paragraph int start=begin*thread_unit; int end = BegiN*thread_unit + thread_unit-1;//last element int min,temp;
		for (int i = start; I <=end; i++) {min = i;
		for (int j = i; J <=end; J + +) {if (data[min]>data[j)) min = j;
			} if (i!= min) {//Exchange data[i] =data[i]+data[min];
			Data[min] = Data[i]-data[min];
		Data[i] = Data[i]-data[min];
	}} void *myprocess (void *arg) {printf ("ThreadID is 0x%x, working on Data%d\n", pthread_self (), * (int *) arg);
	int start = * (int *) arg);//Where the sort begins heapsort (start);
return NULL;
	} void *merge (void *) {//k path merge sort int *start= (int *) malloc (10*sizeof (int));
	int *top= (int *) malloc (10*sizeof (int));
	int *temp= (int *) malloc (num*sizeof (int));
		for (int i=0;i<10;i++) {start[i]=i*10;
	top[i]=10* (i+1);
	The starting position of the int count=0;//temp array begins to merge int mark,minimum,flag;
		while (Count!=num) {flag=0;
					for (int i=0;i<10;i++) {if (Start[i]<top[i]) {//no bounds exceeded if (flag==0) {//only 1 times minimum=start[i];
				Mark=i;//i mark belongs to that section} flag=1;
if (Data[minimum]>data[start[i]]) {					Minimum=start[i];
				Mark=i;
		}} start[mark]++;				
	Temp[count++]=data[minimum];
	for (int i=0;i<num;i++) data[i]=temp[i];
	Free (start);
	Free (top);
	Free (temp);
return NULL;
		int main (int argc, char **argv) {for (int j = 0; j < num; j) {Data[j] = rand ()% 100;
		if (j!=0&&j%thread_unit==0) cout<<endl;	
	cout<<data[j]<< "";
	} cout<<endl;
	Pool_init (thread_num);/* up to 3 active threads/Sleep (1) in the thread pool;
	/* Continuously put 10 tasks into the task queue */int *workingnum = (int *) malloc (sizeof (int) * 10);
	int i;
		for (i = 0; i < i++) {Workingnum[i] = i;
	Add_task (Myprocess, &workingnum[i]);
	Sleep (1);/wait for the previous 10 tasks to complete cout<< "after sorting:" <<endl;
		for (int j = 0; j < num; J +) {if (j!=0&&j%thread_unit==0) cout<<endl;	
	cout<<data[j]<< "";
	} add_task (Merge,null);//FINAL data sort/* Wait for all tasks to complete * * * (20);
	/* Destroy thread pool/Pool_destroy ();
	cout<< "After merging:" <<endl; for (int j = 0; j < num; J +) {
		if (j!=0&&j%thread_unit==0) cout<<endl;	
	cout<<data[j]<< "";
	} cout<<endl;
	Free (workingnum);
return 0; }
Test results:

Initial number of 100:

The 3 newly created processes are sorted by the 100 number of 10 groups, and the data in each group is ordered, with the following results:

At last, the order data of 10 groups were sorted by K-way merging, and the results were as follows:

Visible, these 100 numbers finally all from small to big arrange ....

Note in the program:

Pthread_cond_broadcast (& (Pool->queue_ready));
If we comment out this line, the program will fall into a dead loop because Linux thread execution differs from Windows, Pthread has two states joinable state and unjoinable state, if the thread is joinable state, The stack and thread descriptors (totaling 8K) of the thread are not freed when the thread function returns its own exit or pthread_exit. These resources will be freed only after you have invoked the Pthread_join. In the case of a unjoinable state thread, these resources are thread function ExitOr Pthread_exiT is automatically released. If you do not specify a thread's properties, the thread created by default is the joinable type, where the thread that created the thread (the main thread) calls Phtread_join to wait for the child thread to end and release the child thread's resources. If the line above is commented out, all threads are dormant, and Pthread_join also blocks the main thread ....

Finally, summarize the logic of the above program to create a thread pool:

Step One: Create n threads that first detect whether the task queue is empty and wait for the condition variable if it is empty (that is, when there is a task in the queue);

Step Two: Add the compute task to the task queue, and the process field in the Task Queue task can specify the processing function of the task, and finally call the Pthread_cond_singal to send a signal;

Step Three: Call Pthread_jion wait for all tasks to complete and reclaim resources, and finally destroy the thread pool;

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.