多线程 in C & C++ & Python
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)