我想要做的是將整數值 0 發送到函式以將其用作陣列的索引。但它不是寫給患者 [0],而是寫給患者 [1]。知道為什么嗎?我是從 0 到 1 的簡單回圈,只是為了查看它是否正確傳遞了值 0,將 i(0) 傳遞給函式,將 myArr[0] 分配給某些東西,但它改為分配給 myArr[1]。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
typedef struct patient_info {
pthread_t thread;
char treatment;
char department[20];
} patient;
patient patients[1000];
void* registration(void* arg)
{
int p_num = *((int*)arg); // my array index that supposed to be 0
if (rand() % 2 == 0)
{
patients[p_num].treatment = 'M';
}
else
{
patients[p_num].treatment = 'S';
}
return NULL;
}
int main(void)
{
srand(time(NULL));
for (size_t i = 0; i < 1; i ) // simple for loop to create my thread
{
if (pthread_create(&patients[i].thread, NULL, ®istration, (void*)&i) != 0)
{
perror("There has been an error with pthread_create().");
return 1;
}
}
for (size_t j = 0; j < 1; j )
{
if (pthread_join(patients[j].thread, NULL) != 0)
{
perror("There has been an error with the pthread_join().");
return 2;
}
}
for (size_t i = 0; i < 1000; i ) // make this loop to see where it is writing.
{
if (patients[i].treatment == 'M' || patients[i].treatment == 'S')
{
printf("Treatment is: %c %d\n", patients[i].treatment, i);
}
}
return 0;
}
uj5u.com熱心網友回復:
您將指標傳遞給i,因此每個執行緒都指向同一個 i變數。
因此,執行緒競相獲取它們的價值。(例如) threadA 想要0而 threadB 想要1。但是,如果主任務足夠快,兩者都可能會看到 0或1。因此,沖突。
此外,在main,i是size_t但registration,這是一個int指標。它們[可能]大小不同。
該解決方案是通過i由值
pthread_create(&patients[i].thread, NULL, ®istration, (void *) i)
并且,在 中registration,我們按值接受:
void *
registration(void *arg)
{
size_t p_num = (size_t) arg;
// ...
return (void *) 0;
}
這是更正后的代碼:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
typedef struct patient_info {
pthread_t thread;
char treatment;
char department[20];
} patient;
patient patients[1000];
void *
registration(void *arg)
{
// my array index that supposed to be 0
// NOTE/BUG: this uses the wrong size pointer and to prevent the race condition
// we want to accept by value
#if 0
int p_num = *((int *) arg);
#else
size_t p_num = (size_t) arg;
#endif
if (rand() % 2 == 0) {
patients[p_num].treatment = 'M';
}
else {
patients[p_num].treatment = 'S';
}
return NULL;
}
int
main(void)
{
srand(time(NULL));
// simple for loop to create my thread
for (size_t i = 0; i < 1; i ) {
if (pthread_create(&patients[i].thread, NULL, ®istration,
#if 0
(void *) &i) != 0) {
#else
(void *) i) != 0) {
#endif
perror("There has been an error with pthread_create().");
return 1;
}
}
for (size_t j = 0; j < 1; j ) {
if (pthread_join(patients[j].thread, NULL) != 0) {
perror("There has been an error with the pthread_join().");
return 2;
}
}
// make this loop to see where it is writing.
for (size_t i = 0; i < 1000; i ) {
if (patients[i].treatment == 'M' || patients[i].treatment == 'S') {
printf("Treatment is: %c %d\n", patients[i].treatment, i);
}
}
return 0;
}
由于您已經遇到了創建患者的麻煩struct,我們可以通過使用和傳遞一些指向它的指標來稍微清理代碼struct:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
typedef struct patient_info {
pthread_t thread;
char treatment;
char department[20];
} patient;
patient patients[1000];
void *
registration(void *arg)
{
patient *pt = arg;
if (rand() % 2 == 0) {
pt->treatment = 'M';
}
else {
pt->treatment = 'S';
}
return NULL;
}
int
main(void)
{
srand(time(NULL));
patient *pt;
// simple for loop to create my thread
for (size_t i = 0; i < 1; i ) {
pt = &patients[i];
if (pthread_create(&pt->thread, NULL, ®istration, pt) != 0) {
perror("There has been an error with pthread_create().");
return 1;
}
}
for (size_t j = 0; j < 1; j ) {
pt = &patients[j];
if (pthread_join(pt->thread, NULL) != 0) {
perror("There has been an error with the pthread_join().");
return 2;
}
}
// make this loop to see where it is writing.
for (size_t i = 0; i < 1000; i ) {
pt = &patients[i];
if (pt->treatment == 'M' || pt->treatment == 'S') {
printf("Treatment is: %c %d\n", pt->treatment, i);
}
}
return 0;
}
請注意,我們將患者陣列定義為具有 1000 個元素。
At present, we are only creating one thread.
Presumably, we want to process all 1000 records.
But, creating 1000 threads is problematic and doesn't scale too well. If we had 100,000 patients, we [probably] could not create 100,000 threads in parallel.
And, even if we could, the system would spend most of its time switching between threads and the system would slow to a crawl.
Better to have a "pool" of "worker" threads and feed them a few records at a time.
If we do that, there's no reason to put the pthread_t into the patient record. We can have two separate arrays: one for patients and another [smaller] array for "active" threads.
有很多方法可以做到這一點。理想情況下,我們監視執行緒完成并動態添加新執行緒。但是,第一次嘗試有點復雜。
這是一個將事物分成有限塊的版本。這是“現在足夠好”的解決方案:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
typedef struct patient_info {
char treatment;
char department[20];
} patient;
#define NPATIENT 1000
patient patients[NPATIENT];
#define NWORKER 10
pthread_t threads[NWORKER];
void *
registration(void *arg)
{
patient *pt = arg;
if (rand() % 2 == 0) {
pt->treatment = 'M';
}
else {
pt->treatment = 'S';
}
return NULL;
}
int
main(void)
{
srand(time(NULL));
patient *pt;
for (size_t patlo = 0; patlo < NPATIENT; patlo = NWORKER) {
size_t pathi = patlo NWORKER;
if (pathi > NPATIENT)
pathi = NPATIENT;
size_t itsk;
// simple for loop to create my thread
itsk = 0;
for (size_t ipat = patlo; ipat < pathi; ipat , itsk ) {
pt = &patients[ipat];
if (pthread_create(&threads[itsk], NULL, ®istration, pt) != 0) {
perror("There has been an error with pthread_create().");
return 1;
}
}
// join this chunk of threads
itsk = 0;
for (size_t ipat = patlo; ipat < pathi; ipat , itsk ) {
pt = &patients[ipat];
if (pthread_join(threads[itsk], NULL) != 0) {
perror("There has been an error with the pthread_join().");
return 2;
}
}
}
// make this loop to see where it is writing.
for (size_t ipat = 0; ipat < NPATIENT; ipat ) {
pt = &patients[ipat];
if (pt->treatment == 'M' || pt->treatment == 'S') {
printf("Treatment is: %c %zu\n", pt->treatment, ipat);
}
}
return 0;
}
更新:
但是為什么有必要在你給出的下面的例子中使用指向 struct 的指標?
這不是絕對必要的,但它是一個更清潔、更可擴展的選項。而且,無需編譯器優化,它生成的代碼速度更快。
做起來pt->whatever比patients[i].whatever到處都簡單。
當我只回圈一次(僅創建 1 個執行緒)時,2 個執行緒如何競爭 0 或 1?– 盟約
只有一個執行緒,他們不比賽。但是,如果我們切換到更大的數字(例如)2,他們就會競爭。
請記住,我們解決了兩個問題:
- 比賽條件
iin之間的大小不匹配main,它size_t是 8 位元組,p_num而執行緒函式中的大小是 4。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/369507.html
上一篇:C用n值填充char陣列導致問題
