▶ 关于单链表的访问,插入结点和删除结点操作,并且将其推广到多线程中去。

● 代码,通用的随机数生成

 // my_rand.h
#ifndef _MY_RAND_H_
#define _MY_RAND_H_ unsigned my_rand(unsigned* a_p);
double my_drand(unsigned* a_p); #endif // my_rand.c
#include <stdio.h>
#include <stdlib.h>
#include "my_rand.h" #define MR_MULTIPLIER 279470273
#define MR_INCREMENT 0
#define MR_MODULUS 4294967291U
#define MR_DIVISOR ((double) 4294967291U) #ifdef _MAIN_
int main(void)
{
int n, i;
unsigned seed = , x;
double y;
printf("How many random numbers?\n");
scanf("%d", &n); x = my_rand(&seed);
for (i = ; i < n; i++)
{
x = my_rand(&x);
printf("%u\n", x);
}
for (i = ; i < n; i++)
{
y = my_drand(&x);
printf("%e\n", y);
}
return ;
}
#endif unsigned my_rand(unsigned* seed_p)// 产生 0 ~ MR_MODULUS - 1 之间的随机整数
{
long long z = *seed_p;
z = (z * MR_MULTIPLIER + MR_INCREMENT) % MR_MODULUS;
*seed_p = z;
return z;
} double my_drand(unsigned* seed_p)// 产生 0 ~ 1 之间的随机双精度浮点数
{
return (double)my_rand(seed_p) / MR_DIVISOR;
}

● 代码,单线程

 // linked_list.c
#include <stdio.h>
#include <stdlib.h> struct list_node_s
{
int data;
struct list_node_s* next;
}; int Insert(int value, struct list_node_s** head_pp) // 插入结点
{
struct list_node_s *curr_p, *pred_p, *temp_p;
for (curr_p = *head_pp, pred_p = NULL; curr_p != NULL && curr_p->data < value; pred_p = curr_p, curr_p = curr_p->next);// 搜索目标位置
if (curr_p == NULL || curr_p->data > value) // 找到了目标位置
{
temp_p = malloc(sizeof(struct list_node_s));
temp_p->data = value;
temp_p->next = curr_p;
if (pred_p == NULL)
*head_pp = temp_p;
else
pred_p->next = temp_p;
return ;
}
printf("%d is already in the list\n", value);// 其他情况,目标结点已经存在(链表元素不允许重复)
return ;
} void Print(struct list_node_s* head_p) // 打印单链表
{
struct list_node_s *curr_p;
printf("list = ");
for (curr_p = head_p; curr_p != (struct list_node_s*) NULL; curr_p = curr_p->next)
printf("%d ", curr_p->data);
printf("\n");
return;
} int Member(int value, struct list_node_s* head_p) // 查找元素 value
{
struct list_node_s *curr_p; for (curr_p = head_p; curr_p != NULL && curr_p->data < value; curr_p = curr_p->next);
if (curr_p == NULL || curr_p->data > value)
{
printf("%d is not in the list\n", value);
return ;
}
printf("%d is in the list\n", value);
return ;
} int Delete(int value, struct list_node_s** head_pp) // 删除指定结点
{
struct list_node_s *curr_p = *head_pp, *pred_p = NULL;
for (curr_p = *head_pp, pred_p = NULL; curr_p != NULL && curr_p->data < value; pred_p = curr_p, curr_p = curr_p->next);
if (curr_p != NULL && curr_p->data == value)
{
if (pred_p == NULL)
{
*head_pp = curr_p->next;
# ifdef DEBUG
printf("Freeing %d\n", value);
# endif
free(curr_p);
}
else
{
pred_p->next = curr_p->next;
# ifdef DEBUG
printf("Freeing %d\n", value);
# endif
free(curr_p);
}
return ;
}
printf("%d is not in the list\n", value);
return ;
} int Is_empty(struct list_node_s* head_p) // 判断是否为空表
{
return head_p == NULL;
} void Free_list(struct list_node_s** head_pp) // 释放单链表
{
struct list_node_s *curr_p, *succ_p;
if (Is_empty(*head_pp))
return;
for (curr_p = *head_pp, succ_p = curr_p->next; succ_p != NULL; free(curr_p), curr_p = succ_p, succ_p = curr_p->next)
{
# ifdef DEBUG
printf("Freeing %d\n", curr_p->data);
# endif
}
# ifdef DEBUG
printf("Freeing %d\n", curr_p->data);
# endif
free(curr_p);
*head_pp = NULL;
} char Get_command(void) // 读取下一个命令字符
{
char c;
printf("Please enter a command: ");
scanf(" %c", &c);
return c;
} int Get_value(void) // 读取下一个命令值
{
int val;
printf("Please enter a value: ");
scanf("%d", &val);
return val;
} int main(void)
{
char command;
int value;
struct list_node_s *head_p = NULL;
for (command = Get_command(); command != 'q' && command != 'Q';)
{
switch (command)// 逐命令运行,忽略个操作函数的返回值
{
case 'i':
case 'I':
value = Get_value();
Insert(value, &head_p);
break;
case 'p':
case 'P':
Print(head_p);
break;
case 'm':
case 'M':
value = Get_value();
Member(value, head_p);
break;
case 'd':
case 'D':
value = Get_value();
Delete(value, &head_p);
break;
default:
printf("There is no %c command\n", command);
printf("Please try again\n");
}
command = Get_command();
}
Free_list(&head_p);
return ;
}

● 代码,使用单互斥量

 #include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "my_rand.h" const int MAX_KEY = ; struct list_node_s
{
int data;
struct list_node_s* next;
}; struct list_node_s *head = NULL;// 链表头结点
int thread_count; // 线程数
int total_ops; // 总操作数
double insert_percent; // 插入操作比例
double search_percent; // 查找操作比例
double delete_percent; // 删除操作比例
pthread_mutex_t mutex; // 线程操作互斥量
pthread_mutex_t count_mutex; // 线程操作数写入全局和时候的互斥量
int member_total = , insert_total = , delete_total = ;// 全局操作数统计 void Usage(char* prog_name)
{
fprintf(stderr, "usage: %s <thread_count>\n", prog_name);
exit();
} void Get_input(int* inserts_in_main_p)// 主函数中用于输入的函数
{
printf("How many keys should be inserted in the main thread?\n");
scanf("%d", inserts_in_main_p);
printf("How many total ops should be executed?\n");
scanf("%d", &total_ops);
printf("Percent of ops that should be searches? (between 0 and 1)\n");
scanf("%lf", &search_percent);
printf("Percent of ops that should be inserts? (between 0 and 1)\n");
scanf("%lf", &insert_percent);
delete_percent = 1.0 - (search_percent + insert_percent);
} int Insert(int value)// 插入结点
{
struct list_node_s *curr, *pred, *temp;
for (curr = head, pred = NULL; curr != NULL && curr->data < value; pred = curr, curr = curr->next);
if (curr == NULL || curr->data > value)
{
temp = malloc(sizeof(struct list_node_s));
temp->data = value;
temp->next = curr;
if (pred == NULL)
head = temp;
else
pred->next = temp;
return ;
}
printf("%d is already in the list\n", value);
return ;
} void Print(void)
{
struct list_node_s *temp;
printf("list = ");
for (temp = head; temp != (struct list_node_s*) NULL; temp = temp->next)
printf("%d ", temp->data);
printf("\n");
} int Member(int value)
{
struct list_node_s *temp;
for (temp = head; temp != NULL && temp->data < value; temp = temp->next);
if (temp == NULL || temp->data > value)
{
# ifdef DEBUG
printf("%d is not in the list\n", value);
# endif
return ;
}
# ifdef DEBUG
printf("%d is in the list\n", value);
# endif
return ;
} int Delete(int value)
{
struct list_node_s *curr, *pred;
for (curr = head, pred = NULL; curr != NULL && curr->data < value; pred = curr, curr = curr->next);
if (curr != NULL && curr->data == value)
{
if (pred == NULL)
head = curr->next;
else
pred->next = curr->next;
# ifdef DEBUG
printf("Freeing %d\n", value);
# endif
free(curr);
return ;
}
return ;
} int Is_empty(void)
{
return head == NULL;
} void Free_list(void)
{
struct list_node_s *current, *following;
if (Is_empty())
return;
for (current = head, following = current->next; following != NULL; free(current), current = following, following = current->next)
{
# ifdef DEBUG
printf("Freeing %d\n", current->data);
# endif
}
# ifdef DEBUG
printf("Freeing %d\n", current->data);
# endif
free(current);
} void* Thread_work(void* rank)// 调度各种链表工作的函数
{
int i, my_member, my_insert, my_delete;
unsigned seed = (long)rank + ;
double which_op;
for (i = my_member = my_insert = my_delete = ; i < total_ops / thread_count; i++)
{
which_op = my_drand(&seed);
if (which_op < search_percent)// 随机数小于设定的搜索概率,执行搜索操作
{
pthread_mutex_lock(&mutex);
Member(my_rand(&seed) % MAX_KEY);
pthread_mutex_unlock(&mutex);
my_member++;
}
else if (which_op < search_percent + insert_percent)// 随机数小于搜索和插入概率,执行插入
{
pthread_mutex_lock(&mutex);
Insert(my_rand(&seed) % MAX_KEY);
pthread_mutex_unlock(&mutex);
my_insert++;
}
else// 随机数大于搜索和插入的概率,执行删除操作
{
pthread_mutex_lock(&mutex);
Delete(my_rand(&seed) % MAX_KEY);
pthread_mutex_unlock(&mutex);
my_delete++;
}
}
pthread_mutex_lock(&count_mutex);// 将操作数加入总计数据中
member_total += my_member;
insert_total += my_insert;
delete_total += my_delete;
pthread_mutex_unlock(&count_mutex);
return NULL;
} int main(int argc, char* argv[])
{
int i, attempts, inserts_in_main;
unsigned seed = ;
pthread_t *thread_handles;
if (argc != ) Usage(argv[]);
thread_count = strtol(argv[], NULL, );
Get_input(&inserts_in_main); for (i = attempts = ; i < inserts_in_main && attempts < * inserts_in_main; attempts++)// 尝试先插入 2 * inserts_in_main 个结点
{
if (Insert(my_rand(&seed) % MAX_KEY))
i++;
}
printf("Inserted %ld keys in empty list\n", i);
# ifdef OUTPUT
printf("Before starting threads, list = \n");
Print();
printf("\n");
# endif
thread_handles = malloc(thread_count * sizeof(pthread_t));
pthread_mutex_init(&mutex, NULL);
pthread_mutex_init(&count_mutex, NULL);
for (i = ; i < thread_count; i++)
pthread_create(&thread_handles[i], NULL, Thread_work, (void*)i);
for (i = ; i < thread_count; i++)
pthread_join(thread_handles[i], NULL);
printf("Total ops = %d\n", total_ops);
printf("member ops = %d\n", member_total);
printf("insert ops = %d\n", insert_total);
printf("delete ops = %d\n", delete_total);
# ifdef OUTPUT
printf("After threads terminate, list = \n");
Print();
printf("\n");
# endif
Free_list();
pthread_mutex_destroy(&mutex);
pthread_mutex_destroy(&count_mutex);
free(thread_handles);
return ;
}

● 代码,使用多互斥量,每个结点一个互斥量

 #include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "my_rand.h" const int MAX_KEY = ;
const int IN_LIST = ;
const int EMPTY_LIST = -;
const int END_OF_LIST = ; struct list_node_s// 重新定义了单链表结点,每个结点增加一个互斥量
{
int data;
pthread_mutex_t mutex;
struct list_node_s* next;
}; struct list_node_s* head = NULL;
pthread_mutex_t head_mutex;
int thread_count;
int total_ops;
double insert_percent;
double search_percent;
double delete_percent;
pthread_mutex_t count_mutex;
int member_total = , insert_total = , delete_total = ; void Usage(char* prog_name)
{
fprintf(stderr, "usage: %s <thread_count>\n", prog_name);
exit();
} void Get_input(int* inserts_in_main_p)
{
printf("How many keys should be inserted in the main thread?\n");
scanf("%d", inserts_in_main_p);
printf("How many total ops should be executed?\n");
scanf("%d", &total_ops);
printf("Percent of ops that should be searches? (between 0 and 1)\n");
scanf("%lf", &search_percent);
printf("Percent of ops that should be inserts? (between 0 and 1)\n");
scanf("%lf", &insert_percent);
delete_percent = 1.0 - (search_percent + insert_percent);
} void Init_ptrs(struct list_node_s** curr_pp, struct list_node_s** pred_pp)// 初始化结点指针对 *curr_pp 和 *pred_pp
{
*pred_pp = NULL;
pthread_mutex_lock(&head_mutex);
*curr_pp = head;
if (*curr_pp != NULL)
pthread_mutex_lock(&((*curr_pp)->mutex));
// pthread_mutex_unlock(&head_mutex);
return;
} int Advance_ptrs(struct list_node_s** curr_pp, struct list_node_s** pred_pp)// 将结点指针 *curr_pp 和 *pred_pp 向后移动一格
{
struct list_node_s* curr_p = *curr_pp, *pred_p = *pred_pp;
if (curr_p == NULL)
{
if (pred_p == NULL)
{
pthread_mutex_unlock(&head_mutex);
return EMPTY_LIST;
}
else
return END_OF_LIST;
}
if (curr_p->next != NULL)
pthread_mutex_lock(&(curr_p->next->mutex));
if (pred_p != NULL)
pthread_mutex_unlock(&(pred_p->mutex));
else
pthread_mutex_unlock(&head_mutex);
*pred_pp = curr_p, *curr_pp = curr_p->next;
return (curr_p->next == NULL) ? END_OF_LIST : IN_LIST;
} int Insert(int value)
{
struct list_node_s *curr, *pred, *temp;
for (Init_ptrs(&curr, &pred); curr != NULL && curr->data < value; Advance_ptrs(&curr, &pred));
if (curr == NULL || curr->data > value)
{
# ifdef DEBUG
printf("Inserting %d\n", value);
# endif
temp = malloc(sizeof(struct list_node_s));
pthread_mutex_init(&(temp->mutex), NULL);
temp->data = value;
temp->next = curr;
if (curr != NULL)
pthread_mutex_unlock(&(curr->mutex));
if (pred == NULL)
{
head = temp;
pthread_mutex_unlock(&head_mutex);
}
else
{
pred->next = temp;
pthread_mutex_unlock(&(pred->mutex));
}
return ;
}
if (curr != NULL)
pthread_mutex_unlock(&(curr->mutex));
if (pred != NULL)
pthread_mutex_unlock(&(pred->mutex));
else
pthread_mutex_unlock(&head_mutex);
return ;
} void Print(void)// 注意不使用互斥量
{
struct list_node_s *temp;
printf("list = ");
for (temp = head; temp != (struct list_node_s*) NULL; temp = temp->next)
printf("%d ", temp->data);
printf("\n");
} int Member(int value)
{
struct list_node_s *temp, *old_temp;
pthread_mutex_lock(&head_mutex);
if (head != NULL)
pthread_mutex_lock(&(head->mutex));
pthread_mutex_unlock(&head_mutex);
for (temp = head; temp != NULL && temp->data < value;)
{
if (temp->next != NULL)
pthread_mutex_lock(&(temp->next->mutex));
old_temp = temp;
temp = temp->next;
pthread_mutex_unlock(&(old_temp->mutex));
}
if (temp == NULL || temp->data > value)
{
# ifdef DEBUG
printf("%d is not in the list\n", value);
# endif
if (temp != NULL)
pthread_mutex_unlock(&(temp->mutex));
return ;
}
# ifdef DEBUG
printf("%d is in the list\n", value);
# endif
pthread_mutex_unlock(&(temp->mutex));
return ;
} int Delete(int value)
{
struct list_node_s *curr, *pred;
for (Init_ptrs(&curr, &pred); curr != NULL && curr->data < value; Advance_ptrs(&curr, &pred));
if (curr != NULL && curr->data == value)
{
if (pred == NULL)
{
head = curr->next;
# ifdef DEBUG
printf("Freeing %d\n", value);
# endif
pthread_mutex_unlock(&head_mutex);
pthread_mutex_unlock(&(curr->mutex));
pthread_mutex_destroy(&(curr->mutex));
free(curr);
}
else
{
pred->next = curr->next;
pthread_mutex_unlock(&(pred->mutex));
# ifdef DEBUG
printf("Freeing %d\n", value);
# endif
pthread_mutex_unlock(&(curr->mutex));
pthread_mutex_destroy(&(curr->mutex));
free(curr);
}
return ;
}
if (pred != NULL)
pthread_mutex_unlock(&(pred->mutex));
if (curr != NULL)
pthread_mutex_unlock(&(curr->mutex));
if (curr == head)
pthread_mutex_unlock(&head_mutex);
return ;
} int Is_empty(void)
{
return head == NULL;
} void Free_list(void)
{
struct list_node_s *current, *following;
if (Is_empty())
return;
for (current = head, following = current->next; following != NULL; free(current), current = following, following = current->next)
{
# ifdef DEBUG
printf("Freeing %d\n", current->data);
# endif
}
# ifdef DEBUG
printf("Freeing %d\n", current->data);
# endif
free(current);
} void* Thread_work(void* rank)
{
unsigned seed = (long)rank + ;
int i, my_member, my_insert, my_delete;
double which_op;
for (i = my_member = my_insert = my_delete = ; i < total_ops / thread_count; i++)
{
which_op = my_drand(&seed);
if (which_op < search_percent)
{
# ifdef DEBUG
printf("Thread %ld > Searching for %d\n", my_rank, val);
# endif
Member(my_rand(&seed) % MAX_KEY);
my_member++;
}
else if (which_op < search_percent + insert_percent)
{
# ifdef DEBUG
printf("Thread %ld > Attempting to insert %d\n", my_rank, val);
# endif
Insert(my_rand(&seed) % MAX_KEY);
my_insert++;
}
else
{
# ifdef DEBUG
printf("Thread %ld > Attempting to delete %d\n", my_rank, val);
# endif
Delete(my_rand(&seed) % MAX_KEY);
my_delete++;
}
}
pthread_mutex_lock(&count_mutex);
member_total += my_member;
insert_total += my_insert;
delete_total += my_delete;
pthread_mutex_unlock(&count_mutex);
return NULL;
} int main(int argc, char* argv[])
{
int i, attempts, inserts_in_main;
unsigned seed = ;
pthread_t* thread_handles;
if (argc != ) Usage(argv[]);
thread_count = strtol(argv[], NULL, );
Get_input(&inserts_in_main); for (i = attempts = ; i < inserts_in_main && attempts < * inserts_in_main; attempts++)
{
if (Insert(my_rand(&seed) % MAX_KEY))
i++;
}
printf("Inserted %ld keys in empty list\n", i);
# ifdef OUTPUT
printf("Before starting threads, list = \n");
Print();
printf("\n");
# endif
thread_handles = malloc(thread_count * sizeof(pthread_t));
pthread_mutex_init(&head_mutex, NULL);
pthread_mutex_init(&count_mutex, NULL);
for (i = ; i < thread_count; i++)
pthread_create(&thread_handles[i], NULL, Thread_work, (void*)i);
for (i = ; i < thread_count; i++)
pthread_join(thread_handles[i], NULL);
printf("Total ops = %d\n", total_ops);
printf("member ops = %d\n", member_total);
printf("insert ops = %d\n", insert_total);
printf("delete ops = %d\n", delete_total);
# ifdef OUTPUT
printf("After threads terminate, list = \n");
Print();
printf("\n");
# endif
Free_list();
pthread_mutex_destroy(&head_mutex);
pthread_mutex_destroy(&count_mutex);
free(thread_handles);
return ;
}

● 代码,使用读写锁

 #include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "my_rand.h" const int MAX_KEY = ; struct list_node_s
{
int data;
struct list_node_s* next;
}; struct list_node_s *head = NULL;
int thread_count;
int total_ops;
double insert_percent;
double search_percent;
double delete_percent;
pthread_rwlock_t rwlock; // 读写锁
pthread_mutex_t count_mutex;
int member_total = , insert_total = , delete_total = ; void Usage(char* prog_name)
{
fprintf(stderr, "usage: %s <thread_count>\n", prog_name);
exit();
} void Get_input(int* inserts_in_main_p)
{
printf("How many keys should be inserted in the main thread?\n");
scanf("%d", inserts_in_main_p);
printf("How many total ops should be executed?\n");
scanf("%d", &total_ops);
printf("Percent of ops that should be searches? (between 0 and 1)\n");
scanf("%lf", &search_percent);
printf("Percent of ops that should be inserts? (between 0 and 1)\n");
scanf("%lf", &insert_percent);
delete_percent = 1.0 - (search_percent + insert_percent);
} int Insert(int value)
{
struct list_node_s *curr, *pred = NULL, *temp;
for (curr = head, pred = NULL; curr != NULL && curr->data < value; pred = curr, curr = curr->next);
if (curr == NULL || curr->data > value)
{
temp = malloc(sizeof(struct list_node_s));
temp->data = value;
temp->next = curr;
if (pred == NULL)
head = temp;
else
pred->next = temp;
return ;
}
return ;
} void Print(void)
{
struct list_node_s *temp;
printf("list = ");
for (temp = head; temp != (struct list_node_s*) NULL; temp = temp->next)
printf("%d ", temp->data);
printf("\n");
} int Member(int value)
{
struct list_node_s *temp;
for (temp = head; temp != NULL && temp->data < value; temp = temp->next);
if (temp == NULL || temp->data > value)
{
# ifdef DEBUG
printf("%d is not in the list\n", value);
# endif
return ;
}
# ifdef DEBUG
printf("%d is in the list\n", value);
# endif
return ;
} int Delete(int value)
{
struct list_node_s *curr, *pred;
for (curr = head, pred = NULL; curr != NULL && curr->data < value; pred = curr, curr = curr->next);
if (curr != NULL && curr->data == value)
{
if (pred == NULL)
head = curr->next;
else
pred->next = curr->next;
# ifdef DEBUG
printf("Freeing %d\n", value);
# endif
free(curr);
return ;
}
return ;
} int Is_empty(void)
{
return head == NULL;
} void Free_list(void)
{
struct list_node_s *current, *following;
if (Is_empty())
return;
for (current = head, following = current->next; following != NULL; free(current), current = following, following = current->next)
{
# ifdef DEBUG
printf("Freeing %d\n", current->data);
# endif
}
# ifdef DEBUG
printf("Freeing %d\n", current->data);
# endif
free(current);
} void* Thread_work(void* rank)
{
int i, my_member, my_insert, my_delete;
unsigned seed = (long)rank + ;
double which_op;
for (i = my_member = my_insert = my_delete = ; i < total_ops / thread_count; i++)
{
which_op = my_drand(&seed);
if (which_op < search_percent)
{
pthread_rwlock_rdlock(&rwlock);
Member(my_rand(&seed) % MAX_KEY);
pthread_rwlock_unlock(&rwlock);
my_member++;
}
else if (which_op < search_percent + insert_percent)
{
pthread_rwlock_wrlock(&rwlock);
Insert(my_rand(&seed) % MAX_KEY);
pthread_rwlock_unlock(&rwlock);
my_insert++;
}
else
{
pthread_rwlock_wrlock(&rwlock);
Delete(my_rand(&seed) % MAX_KEY);
pthread_rwlock_unlock(&rwlock);
my_delete++;
}
}
pthread_mutex_lock(&count_mutex);
member_total += my_member;
insert_total += my_insert;
delete_total += my_delete;
pthread_mutex_unlock(&count_mutex);
return NULL;
} int main(int argc, char* argv[])
{
int i, attempts, inserts_in_main;
unsigned seed = ;
pthread_t *thread_handles;
if (argc != ) Usage(argv[]);
thread_count = strtol(argv[], NULL, );
Get_input(&inserts_in_main); for (i = attempts = ; i < inserts_in_main && attempts < * inserts_in_main; attempts++)
{
if (Insert(my_rand(&seed) % MAX_KEY))
i++;
}
printf("Inserted %ld keys in empty list\n", i);
# ifdef OUTPUT
printf("Before starting threads, list = \n");
Print();
printf("\n");
# endif
thread_handles = malloc(thread_count * sizeof(pthread_t));
pthread_mutex_init(&count_mutex, NULL);
pthread_rwlock_init(&rwlock, NULL);
for (i = ; i < thread_count; i++)
pthread_create(&thread_handles[i], NULL, Thread_work, (void*)i);
for (i = ; i < thread_count; i++)
pthread_join(thread_handles[i], NULL);
printf("Total ops = %d\n", total_ops);
printf("member ops = %d\n", member_total);
printf("insert ops = %d\n", insert_total);
printf("delete ops = %d\n", delete_total);
# ifdef OUTPUT
printf("After threads terminate, list = \n");
Print();
printf("\n");
# endif
Free_list();
pthread_rwlock_destroy(&rwlock);
pthread_mutex_destroy(&count_mutex);
free(thread_handles);
return ;
}

Pthreads 《并行程序设计导论》的补充代码的更多相关文章

  1. 《并行程序设计导论》——MPI(Microsoft MPI)(1):Hello

    =================================版权声明================================= 版权声明:原创文章 禁止转载  请通过右侧公告中的“联系邮 ...

  2. OpenMP 《并行程序设计导论》的补充代码

    ▶ 使用 OpenMP 和队列数据结构,在各线程之间传递信息 ● 代码,使用 critical 子句和 atomic 指令来进行读写保护 // queue.h #ifndef _QUEUE_H_ #d ...

  3. 《并行程序设计导论》——Pthreads

    这部分不需要看了. 因为C++11和BOOST比这个Pthreads要好一点. 如果不考虑移植性,在Windows平台上用核心编程的东西比C++11和BOOST更好控制.

  4. 《并行程序设计导论》——OpenMP

    OpenMP看着很好,实际上坑很多. 如果真的要求性能和利用率,还是专门写代码吧.而且MS的VS里只有2.X的版本.

  5. 《并行程序设计导论》——MPI(Microsoft MPI)(6):并行排序算法

    =================================版权声明================================= 版权声明:原创文章 禁止转载  请通过右侧公告中的“联系邮 ...

  6. OpenMP并行程序设计

    1.fork/join并行执行模式的概念 2.OpenMP指令和库函数介绍 3.parallel 指令的用法 4.for指令的使用方法 5 sections和section指令的用法 1.fork/j ...

  7. OpenMP并行程序设计——for循环并行化详解

    在C/C++中使用OpenMP优化代码方便又简单,代码中需要并行处理的往往是一些比较耗时的for循环,所以重点介绍一下OpenMP中for循环的应用.个人感觉只要掌握了文中讲的这些就足够了,如果想要学 ...

  8. 《CUDA并行程序设计:GPU编程指南》

    <CUDA并行程序设计:GPU编程指南> 基本信息 原书名:CUDA Programming:A Developer’s Guide to Parallel Computing with ...

  9. openMP编程(上篇)之并行程序设计

    openMP简介 openMP是一个编译器指令和库函数的集合,主要是为共享式存储计算机上的并行程序设计使用的. 当计算机升级到多核时,程序中创建的线程数量需要随CPU核数变化,如在CPU核数超过线程数 ...

随机推荐

  1. poj3734矩阵快速幂

    挑战上面的题目,感觉脑洞很大 分别找红蓝个数全为偶,全为奇,一奇一偶的个数ai,bi,ci 转移矩阵是| 2 1 0 |,是一个对称矩阵(会不会有什么联系.) | 2 2 2 | | 0 1 2 | ...

  2. How to have matlab tic toc in C++?

    Reprinted form: https://stackoverflow.com/questions/13485266/how-to-have-matlab-tic-toc-in-c/1348558 ...

  3. 安装完Linux Mint后,发现系统中竟没有中文输入法

    安装完Linux Mint后,发现系统中竟没有中文输入法,语言支持之后自动更新过程中有些安装包下载失败. 可以采取下面的方法安装上中文输入法. 1. 安装iBus: sudo add-apt-repo ...

  4. 菜鸟帮你跳过openstack配置过程中的坑[文末新添加福利]

    一:前言 对于一个以前做java全栈工程师而言,而且没学过Linux,很少用虚拟机(还是在大学的时候简单的用过),去配置openstack我想我入的坑肯定比有基础的一定要多,躺在每个坑中徘徊思索的时间 ...

  5. oracle用户 密码永不过期

    ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED;

  6. vue-cli脚手架目录讲解

    build目录 config目录 是webpack配置相关的 node-modules目录 是我们用npm install 安装的依赖代码库 src目录 是我们项目的源码(我们开发的所有项目文件都在s ...

  7. 使用QQ邮箱SMTP服务的javamail配置

    最近做一个小项目要用到JAVA的邮箱的发送功能.遇到一些坑这里记录分享一下:QQ群交流:697028234 1.QQ邮箱一定要设置开通SMTP/POP这项.并生成授权码. 2.用MAVEN生成一个QU ...

  8. 开源FTP软件FileZilla使用介绍

    简介 FileZilla是一个优秀的开源FTP软件,分为客户端版本和服务器版本,具备所有的FTP软件功能,如果想自己搭建FTP服务器,FileZilla是一个好选择. 下载 FileZilla有一个中 ...

  9. IIR滤波器设计(调用MATLAB IIR函数来实现)

    转载请注明文章来源 – http://blog.csdn.net/v_hyx ,请勿用于任何商业用途         对于滤波器设计,以前虽然学过相关的理论(现代数字信号处理和DSP设计),但一直不求 ...

  10. Mysql5.7的gtid主从半同步复制和组复制

    (一)gtid主从半同步复制 一.半同步复制原理 mysql默认的复制是异步的,主库在执行完客户端提交的事务后会立即将结果返回给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主库如果cr ...