零碎知识点

  1. 栈的大小:

答:1MB,大概10^6字节,可以存25W个int

实现memcpy函数

  1. void *memcpy(void *dest, const void *src, size_t n)

从存储区src复制n个字符到dest

考虑步长对齐和内存重叠问题

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. void *my_memcpy(void *dst, const void *src, int n)
  4. {
  5. if (dst == NULL || src == NULL || n <= 0)
  6. return NULL;
  7. char * pdst = (char *)dst;
  8. char * psrc = (char *)src;
  9. if (pdst > psrc && pdst < psrc + n)
  10. {
  11. pdst = pdst + n - 1;
  12. psrc = psrc + n - 1;
  13. while (n--)
  14. *pdst-- = *psrc--;
  15. }
  16. else
  17. {
  18. while (n--)
  19. *pdst++ = *psrc++;
  20. }
  21. return dst;
  22. }
  23. int main(){
  24. char src[] = "Helloaaaaaa";
  25. char dest[] = "My lady";
  26. my_memcpy(dest, src, 20);
  27. printf("%s\n", dest);
  28. return 0;
  29. }

如何在main函数之前让函数执行?

1.全局类的构造函数
2.将函数返回值赋值

  1. #include<iostream>
  2. using namespace std;
  3. class Test {
  4. public:
  5. Test();
  6. int test2();
  7. };
  8. Test::Test() {
  9. cout << "Test" << endl;
  10. }
  11. int Test::test2() {
  12. cout << "Test2" << endl;
  13. return 0;
  14. }
  15. Test ts;
  16. int a = ts.test2();
  17. int main() {
  18. cout << "main" << endl;
  19. //ts.test2();
  20. return 0;
  21. }

三次握手和四次挥手

三次握手.png
四次挥手.png

生产者消费者问题-互斥锁-线程同步

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <pthread.h>
  5. #include <vector>
  6. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  7. int num = 0;
  8. void *producer(void*){
  9. int times = 10000000;
  10. while(times --){
  11. pthread_mutex_lock(&mutex);
  12. num += 1;
  13. pthread_mutex_unlock(&mutex);
  14. }
  15. }
  16. void *comsumer(void*){
  17. int times = 10000000;
  18. while(times --){
  19. pthread_mutex_lock(&mutex);
  20. num -= 1;
  21. pthread_mutex_unlock(&mutex);
  22. }
  23. }
  24. int main(){
  25. printf("Start in main function.");
  26. pthread_t thread1, thread2;
  27. pthread_create(&thread1, NULL, &producer, NULL);
  28. pthread_create(&thread2, NULL, &comsumer, NULL);
  29. pthread_join(thread1, NULL);
  30. pthread_join(thread2, NULL);
  31. printf("Print in main function: num = %d\n", num);
  32. return 0;
  33. }

编译:一定要加-lpthread参数

  1. g++ mutex_lock_demo.cpp -o lock -lpthread

结果分析

不加锁:每次的结果都不同 加锁:结果为0

条件变量-线程同步

通常与互斥锁配合使用

  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <vector>
  5. #include <queue>
  6. #include <unistd.h>
  7. #include <pthread.h>
  8. int MAX_BUF = 100;
  9. int num = 0;
  10. pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  11. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  12. void* producer(void*){
  13. while(true){
  14. pthread_mutex_lock(&mutex);
  15. while (num >= MAX_BUF){
  16. // 等待
  17. printf("缓冲区满了, 等待消费者消费...\n");
  18. pthread_cond_wait(&cond, &mutex); //休眠并解锁,等待
  19. }
  20. num += 1;
  21. printf("生产一个产品,当前产品数量为:%d\n", num);
  22. sleep(1);
  23. pthread_cond_signal(&cond);
  24. printf("通知消费者...\n");
  25. pthread_mutex_unlock(&mutex);
  26. sleep(1);
  27. }
  28. }
  29. void* consumer(void*){
  30. while(true){
  31. pthread_mutex_lock(&mutex);
  32. while (num <= 0){
  33. // 等待
  34. printf("缓冲区空了, 等待生产者生产...\n");
  35. pthread_cond_wait(&cond, &mutex); //休眠并解锁,等待
  36. }
  37. num -= 1;
  38. printf("消费一个产品,当前产品数量为:%d\n", num);
  39. sleep(1);
  40. pthread_cond_signal(&cond);
  41. printf("通知生产者...\n");
  42. pthread_mutex_unlock(&mutex);
  43. }
  44. }
  45. int main(){
  46. pthread_t thread1, thread2;
  47. pthread_create(&thread1, NULL, &consumer, NULL);
  48. pthread_create(&thread2, NULL, &producer, NULL);
  49. pthread_join(thread1, NULL);
  50. pthread_join(thread2, NULL);
  51. return 0;
  52. }

父进程子进程

  1. #include <iostream>
  2. #include <cstring>
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. using namespace std;
  6. int main()
  7. {
  8. pid_t pid;
  9. int num = 888;
  10. pid = fork();
  11. if(pid == 0){
  12. cout << "这是一个子进程." << endl;
  13. cout << "num in son process: " << num << endl;
  14. while(true){
  15. num += 1;
  16. cout << "num in son process: " << num << endl;
  17. sleep(1);
  18. }
  19. }
  20. else if(pid > 0){
  21. cout << "这是一个父进程." << endl;
  22. cout << "子进程id: " << pid << endl;
  23. cout << "num in father process: " << num << endl;
  24. while(true){
  25. num -= 1;
  26. cout << "num in father process: " << num << endl;
  27. sleep(1);
  28. }
  29. }
  30. else if (pid < 0){
  31. cout << "创建进程失败." << endl;
  32. }
  33. return 0;
  34. }

读写锁-线程同步

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <pthread.h>
  5. #include <vector>
  6. int num = 0;
  7. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  8. pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
  9. void *reader(void*){
  10. int times = 10000000;
  11. while(times --){
  12. // pthread_rwlock_rdlock(&rwlock);
  13. pthread_mutex_lock(&mutex);
  14. if (times % 1000 == 0){
  15. // printf("print num in reader: num = %d\n", num);
  16. // sleep(1);
  17. usleep(10);
  18. }
  19. pthread_mutex_unlock(&mutex);
  20. // pthread_rwlock_unlock(&rwlock);
  21. }
  22. }
  23. void *writer(void*){
  24. int times = 10000000;
  25. while(times --){
  26. pthread_mutex_lock(&mutex);
  27. // pthread_rwlock_wrlock(&rwlock);
  28. num += 1;
  29. // pthread_rwlock_unlock(&rwlock);
  30. pthread_mutex_unlock(&mutex);
  31. }
  32. }
  33. int main(){
  34. printf("Start in main function.\n");
  35. pthread_t thread1, thread2, thread3;
  36. pthread_create(&thread1, NULL, &reader, NULL);
  37. pthread_create(&thread2, NULL, &reader, NULL);
  38. pthread_create(&thread3, NULL, &writer, NULL);
  39. pthread_join(thread1, NULL);
  40. pthread_join(thread2, NULL);
  41. pthread_join(thread3, NULL);
  42. printf("Print in main function: num = %d\n", num);
  43. return 0;
  44. }

共享内存-进程间通信

common.h

#ifndef __COMMON_H__
#define __COMMON_H__

#define TEXT_LEN 2048

// 共享内存的数据结构
struct ShmEntry{
    // 是否可以读取共享内存,用于进程间同步
    bool can_read;
    // 共享内存信息
    char msg[2048]; 
};

#endif

server.cpp

#include "common.h"

#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

#include <iostream>

int main()
{
    // 共享内存的结构体
    struct ShmEntry *entry;

    // 1. 申请共享内存
    int shmid = shmget((key_t)1111, sizeof(struct ShmEntry), 0666|IPC_CREAT);
    if (shmid == -1){
        std::cout << "Create share memory error!" << std::endl;
        return -1;
    }

    // 2. 连接到当前进程空间/使用共享内存
    entry = (ShmEntry*)shmat(shmid, 0, 0);
    entry->can_read = 0;
    while (true){
        if (entry->can_read == 1){
            std::cout << "Received message: " << entry->msg << std::endl;
            entry->can_read = 0;
        }else{
            std::cout << "Entry can not read. Sleep 1s." << std::endl;
            sleep(1);
        }
    }
    // 3. 脱离进程空间
    shmdt(entry);

    // 4. 删除共享内存 
    shmctl(shmid, IPC_RMID, 0);

    return 0;
}

client.cpp

#include "common.h"

#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

#include <iostream>

int main()
{
    struct ShmEntry *entry;

    // 1. 申请共享内存
    int shmid = shmget((key_t)1111, sizeof(struct ShmEntry), 0666|IPC_CREAT);
    if (shmid == -1){
        std::cout << "Create share memory error!" << std::endl;
        return -1;
    }

    // 2. 连接到当前进程空间/使用共享内存
    entry = (ShmEntry*)shmat(shmid, 0, 0);
    entry->can_read = 0;
    char buffer[TEXT_LEN];
    while (true){
        if (entry->can_read == 0){
            std::cout << "Input message>>> ";
            fgets(buffer, TEXT_LEN, stdin);
            strncpy(entry->msg, buffer, TEXT_LEN);
            std::cout << "Send message: " << entry->msg << std::endl;
            entry->can_read = 1;
        }
    }
    // 3. 脱离进程空间
    shmdt(entry);

    // 4. 删除共享内存 
    shmctl(shmid, IPC_RMID, 0);

    return 0;
}

socket套接字-进程间通信

server.cpp

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>

#include <iostream>

// 域套接字
#define SOCKET_PATH "./domainsocket"
#define MSG_SIZE 2048

int main()
{
    int socket_fd, accept_fd;
    int ret = 0;
    socklen_t addr_len;
    char msg[MSG_SIZE];
    struct sockaddr_un server_addr;

    // 1. 创建域套接字
    socket_fd = socket(PF_UNIX,SOCK_STREAM,0); //本地套接字
    if(-1 == socket_fd){
        std::cout << "Socket create failed!" << std::endl;
        return -1;
    }
    // 移除已有域套接字路径
    remove(SOCKET_PATH);
    // 内存区域置0
    bzero(&server_addr,sizeof(server_addr));
    server_addr.sun_family = PF_UNIX;
    strcpy(server_addr.sun_path, SOCKET_PATH);

    // 2. 绑定域套接字
    std::cout << "Binding socket..." << std::endl;
    ret = bind(socket_fd,(sockaddr *)&server_addr,sizeof(server_addr));

    if(0 > ret){
        std::cout << "Bind socket failed." << std::endl;
        return -1;
    }

    // 3. 监听套接字
    std::cout << "Listening socket..." << std::endl;
    ret = listen(socket_fd, 10);
    if(-1 == ret){
        std::cout << "Listen failed" << std::endl;
        return -1;
    }
    std::cout << "Waiting for new requests." << std::endl;
    accept_fd = accept(socket_fd, NULL, NULL);

    bzero(msg,MSG_SIZE);

    while(true){
        // 4. 接收&处理信息
        recv(accept_fd, msg, MSG_SIZE, 0);
        std::cout << "Received message from remote: " << msg <<std::endl;
    }

    close(accept_fd);
    close(socket_fd);
    return 0;
}

client.cpp

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>

#include <iostream>

#define SOCKET_PATH "./domainsocket"
#define MSG_SIZE 2048

int main()
{
    int socket_fd;
    int ret = 0;
    char msg[MSG_SIZE];
    struct sockaddr_un server_addr;

    // 1. 创建域套接字
    socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
    if(-1 == socket_fd){
        std::cout << "Socket create failed!" << std::endl;
        return -1;
    }

    // 内存区域置0
    bzero(&server_addr,sizeof(server_addr));
    server_addr.sun_family = PF_UNIX;
    strcpy(server_addr.sun_path, SOCKET_PATH);

    // 2. 连接域套接字
    ret = connect(socket_fd, (sockaddr *)&server_addr, sizeof(server_addr));

    if(-1 == ret){
        std::cout << "Connect socket failed" << std::endl;
        return -1;
    }

    while(true){
        std::cout << "Input message>>> ";
        fgets(msg, MSG_SIZE, stdin);
        // 3. 发送信息
        ret = send(socket_fd, msg, MSG_SIZE, 0);
    }

    close(socket_fd);
    return 0;
}

自旋锁-线程同步

自旋锁会导致阻塞,cpu占用100

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <vector>

pthread_spinlock_t spin_lock;

int num = 0;

void *producer(void*){
    int times = 10000000;
    while(times --){
        pthread_spin_lock(&spin_lock);
        num += 1;
        pthread_spin_unlock(&spin_lock);
    }
}

void *comsumer(void*){
    int times = 10000000;
    while(times --){
        pthread_spin_lock(&spin_lock);
        num -= 1;
        sleep(10);
        pthread_spin_unlock(&spin_lock);
    }
}


int main(){
    printf("Start in main function.\n");
    pthread_spin_init(&spin_lock, 0);
    pthread_t thread1, thread2;
    pthread_create(&thread1, NULL, &producer, NULL);
    pthread_create(&thread2, NULL, &comsumer, NULL);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    printf("Print in main function: num = %d\n", num);
    return 0;
}

线程间共享哪些资源?

独立的资源
共享的资源 堆、全局变量、静态变量

六大排序算法:快排、归并、插入、希尔、堆排序、冒泡。

#include<iostream>
using namespace std;


void bubble_sort(int arr[], int n) {
    for (int i = 0; i <= n; i++) {
        bool flag = false;
        for (int j = 0; j <= n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) { 
                swap(arr[j], arr[j + 1]);
                flag = true;
            }
        }
        if (!flag) break;
    }
}


void insert_sort(int arr[], int n) {
    //空位最多到i
    for (int i = 0; i <= n; i++) {
        int key = arr[i];
        int j = i - 1;
        while (j >= 0 && arr[j] > key) {
            arr[j+1] = arr[j]; 
            j--;
        }
        arr[j + 1] = key;
    }
}

void shell_sort(int arr[], int n) {
    for (int step = n / 2; step > 0; step /= 2) {
        for (int i = 0; i <= n; i += step) {
            int key = arr[i];
            int j = i - step;
            while (j >= 0 && arr[j] > key) {
                arr[j + step] = arr[j];
                j -= step;
            }
            arr[j + step] = key;
        }
    }
}

/*
堆排序
递归和非递归写法
*/
void heapify(int arr[], int root, int n) {
    int left = root * 2;
    int right = root * 2 + 1;
    if (right <= n && arr[right] > arr[left] ) {
        left = right;
    }
    if (left <= n && arr[left] > arr[root]) {
        swap(arr[left], arr[root]);
        heapify(arr, left, n);
    }
}

void heapify2(int arr[], int root, int n) {
    int left = root * 2;
    while (left <= n) {
        int right = left + 1;
        if (right <= n && arr[right] > arr[left]) left = right;
        if (left <= n && arr[left] > arr[root]) {
            swap(arr[left], arr[root]);
            root = left;
            left = root * 2;
        }
        else break;

    }
}

void build_heap(int arr[], int n) {
    for (int i = n / 2; i >= 1; i--) {
        heapify2(arr, i, n);
    }
}
void heap_sort(int arr[], int n) {
    build_heap(arr, n);
    for (int i = n; i >= 1; i--) {
        swap(arr[i], arr[1]);
        heapify2(arr, 1, i-1);
    }
}

/*
快排
两个函数:quick_sort和partition
*/

int partition(int arr[], int l, int r) {
    int temp = arr[l];
    while (l < r) {
        while (l < r && arr[r] >= temp) r--;
        arr[l] = arr[r];
        while (l < r && arr[l] < temp) l++;
        arr[r] = arr[l];
    }
    arr[l] = temp;
    return l;
}
void quick_sort(int arr[], int l, int r) {
    if (l >= r) return;
    int p = partition(arr, l, r);
    quick_sort(arr, l, p - 1);
    quick_sort(arr, p + 1, r);
}


void merge_sort(int arr[], int l, int r) {
    if (l >= r) return;
    int mid = (l + r) / 2;
    merge_sort(arr, l, mid); //返回的一定是一个有序的数组
    merge_sort(arr, mid + 1, r);
    int* tmp = new int[r - l + 1];
    int left_idx = l, r_idx = mid + 1;
    int k = 0;
    while (left_idx <= mid && r_idx <= r) {
        if (arr[left_idx] < arr[r_idx]) tmp[k++] = arr[left_idx++];
        else tmp[k++] = arr[r_idx++];
    }
    while (left_idx <= mid) tmp[k++] = arr[left_idx++];
    while (r_idx <= r) tmp[k++] = arr[r_idx++];
    for (int i = l, j = 0;i<=r; i++, j++) {
        arr[i] = tmp[j];
    } 
    delete[]tmp;
}

int main() {
    int arr[] = {688,-1,5,100,10 ,999 ,3, 5, 7 };
    //heap_sort(arr, 8);
    //quick_sort(arr, 0, 8);
    //bubble_sort(arr, 8);
    //insert_sort(arr, 8);
    //shell_sort(arr, 8);
    merge_sort(arr,0, 8);
    for (int i = 0; i <= 8; i++) {
        cout << arr[i] << endl;
    }
}