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

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

 // 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. hdu 6301 Distinct Values (双指针,水题)

    大意: 给定m个区间, 求构造一个长n且字典序最小的序列, 使得每个区间内的数各不相同 求出每个位置为左端点时向右延伸最大距离, 然后双指针, 每次从set中取最小 #include <iost ...

  2. UVA-140 Bandwidth (回溯+剪枝)

    题目大意:求一个使带宽最小的排列和最小带宽.带宽是指一个字母到其相邻字母的距离最大值. 题目分析:在递归生成全排列的过程中剪枝,剪枝方案还是两个.一.当前解不如最优解优时,减去:二.预测的理想解不必最 ...

  3. vue 点击按钮 input框架获取焦点的方法

    在按钮事件里加上这一段this.$nextTick(() =>{ this.$refs.input.focus()})

  4. 牛客网——C列一列

    链接:https://www.nowcoder.net/acm/contest/71/C来源:牛客网 题目描述 小W在计算一个数列{An},其中A1=1,A2=2,An+2=An+1+An.尽管他计算 ...

  5. ExtJS 6 如何引入Dashboard模版

    最近很多人问我在ext js 6+的版本中怎么引入官方的dashboard模版,正好我好久没写博客了,这里我写一篇博客来说明一下. 在这里以ext js 6.2.1版本为例(注:需要安装Sencha ...

  6. 003——数组(三)count()reset()end()prev()next()current()

    <?php /** * count 统计数组中元素的个数 */ /*$arr=array('blog.com','博客论坛',array('php课程','css课程')); echo coun ...

  7. webpack 提升90%的构建速度 HardSourceWebpackPlugin

    HardSourceWebpackPlugin 插件 不能提升第一次构建的速度,但对于第二次构建能提升99%的构建速度 第一次构建: 第二次: 提升了..,算不出来,反正就是很多啦~~~ npm in ...

  8. 【转】Linux中文件的可读,可写,可执行权限的解读以及chmod,chown,chgrp命令的用法

    chmod是更改文件的权限 chown是改改文件的属主与属组 chgrp只是更改文件的属组. 一.文件权限解读 如上图所示,开头的-rwxrw-r--这一字符串标识文件权限. 这个字符串有10位,可以 ...

  9. VMware 虚拟机快照、克隆、磁盘扩容

    1. 快照 快照是虚拟机某个时间点上完整系统的镜像,可以在虚拟机内部通过快照文件恢复系统到之前的节点. 拍摄快照: 恢复快照: 2. 克隆 克隆是原始虚拟机全部状态的一个拷贝,是脱离原始虚拟机独立存在 ...

  10. Nginx配置IPv6端口监听及务器设置IPV6及Https支持并通过AppStore审核

    一.监听端口 从Nginx 1.3的某个版本起,默认ipv6only是打开的,所以,我们只需要在监听中加入ipv6监听即可,不过推荐都手动加上比较好,代码如下: listen [::]: ipv6on ...