c7w 显出极高兴的样子,将两个指头的长指甲敲着键盘,点头说,“对呀对呀!……多线程有四样写法,你知道么?”

C

C 首先拿下一杀. 编译时记得 -pthread.

  • 创建线程、收获返回值
#include "pthread.h"
#include "stdio.h"
#include "stdlib.h"

#define NUM_THREADS 12

struct ReturnVal {
    int seed;
    long long my_sum;
};

struct InputVal {
    int seed;
    int rubbish;
    struct ReturnVal* ret;
};

// Input: void*
// Output: void*
void* run(void* r_in) {
    struct InputVal* in = (struct InputVal*) r_in;

    printf("I'm a thread! I'm running with seed %d!\n", in->seed);

    srand(in->seed);
    long long my_sum = 0;
    for(long long i = 0; i < 5e7; ++i) {
        my_sum += rand();
    }

    printf("I'm a thread! I'm exiting with output %lld!\n", my_sum);
    in->ret->seed = in->seed; in->ret->my_sum = my_sum;
    return NULL;
}


int main() {

    // Thread IDs
    pthread_t tids[NUM_THREADS];

    struct InputVal in[NUM_THREADS];
    struct ReturnVal ret[NUM_THREADS];

    for (int i = 0; i < NUM_THREADS; ++i) {
        in[i].seed = 3 * i + 2; in[i].rubbish = 0; in[i].ret = ret + i;
        // Create Threads!
        // Params: Thread ID Storage, Thread Attribute, Function, Function args
        int ret = pthread_create(tids + i, NULL, run, in + i);
        if (ret != 0) {
            printf("Create error!\n");
        } else {
            printf("Thread ID %lld created!\n", i, tids[i]);
        }
    }


    for(int i = 0; i < NUM_THREADS; ++i) {
        // Joining threads!
        pthread_join(tids[i], NULL);
        printf("Reaping thread %lld with output %lld!\n", tids[i], ret[i].my_sum);
    }

    return 0;
}

C++

//
// Created by c7w on 2022/4/10.
//

#include <iostream>
#include <thread>
#define NUM_THREADS 12

struct ReturnVal {
    int seed;
    long long my_sum;
};

void run(int seed, int rubbish, ReturnVal* ret) {
    printf("I'm a thread! I'm running with seed %d!\n", seed);

    srand(seed);
    long long my_sum = 0;
    for(long long i = 0; i < 5e7; ++i) {
        my_sum += rand();
    }

    ret->seed = seed; ret->my_sum = my_sum;
    printf("I'm a thread! I'm exiting with output %lld!\n", my_sum);
}

int main() {

    std::thread::id main_thread_id = std::this_thread::get_id();
    printf("Main thread ID: %lld\n", main_thread_id);

    std::thread threads[NUM_THREADS];
    ReturnVal ret[NUM_THREADS];

    for(int i = 0; i < NUM_THREADS; ++i) {
        threads[i] = std::thread(run, i*3+2, 0, ret + i);
        printf("Thread ID %lld created!\n", threads[i].get_id());
    }

    for(int i = 0; i < NUM_THREADS; ++i) {
        std::thread::id id = threads[i].get_id();
        threads[i].join();
        printf("Reaping thread %lld with output %lld!\n", id, ret[i].my_sum);
    }

    return 0;
}
  • mutex
//
// Created by c7w on 2022/4/10.
//

#include <iostream>
#include <thread>
#include <mutex>

volatile int counter(0);
std::mutex mtx;

void attempt_10k_increases() {
    for (int i = 0; i < 10000; ++i) {
        mtx.lock();
        ++counter;
        mtx.unlock();
    }
}

int main() {
    std::thread threads[10];
    for (int i = 0; i < 10; ++i) {
        threads[i] = std::thread(attempt_10k_increases);
    }

    for (auto &th: threads) th.join();
    std::cout << counter << " successful increases of the counter.\n";

    return 0;
}

C Sharp

Python

Python 本身是单线程执行,同一时刻只有一个线程可以执行 Python 代码。于是我们用 multiprocessing 产生多个进程。

from multiprocessing import Process
import random

NUM_THREADS = 12

def run(seed: int, rubbish: int):
    random.seed(seed)
    print(f"I'm a thread! I'm running with seed {seed}!");

    my_sum = 0

    for i in range(10_000_000):
        my_sum += random.random();

    print(f"I'm a thread! I'm exiting with output {my_sum}!");

if __name__ == "__main__":
    process_list = []

    # Start multi-processing
    for i in range(NUM_THREADS):
        process_list.append(Process(target=run, args=(3*i+2, 0)))
        process_list[-1].start()

    # Wait for joining
    for i in range(NUM_THREADS):
        process_list[i].join()
  • 共享数据(也可用于无序取回返回值)
from multiprocessing import Process, Queue

def f(q):
    q.put([42, None, 'hello'])
    q.put('h22ello')

if __name__ == '__main__':
    q = Queue()
    p = Process(target=f, args=(q,))
    p.start()
    print(q.get())    # prints "[42, None, 'hello']"
    print(q.get())    # prints "'h22ello'"
    print(q.get())    # Block the process until next item arrives
    p.join()
  • 使用 p_tqdm(也可用于有序取回返回值)
from p_tqdm import p_map

l1 = ['1', '2', '3']
l2 = ['a', 'b', 'c']


def add(a, b):
    return a + b


added = p_map(add, l1, l2)
print(added)

Java