如何使用 pthreads 以对具有约束的数组执行同时操作?
How to use pthreads in order to perform simultaneous operations on an array with constraint?
我在 C 中使用 pthreads 以便对 int
数组执行两个操作:一个操作将单元格的值加倍,另一个操作将单元格的值减半。如果在将单元格加倍后,其值将变得大于线程需要等待的最大允许值,直到另一个线程将该单元格的值减半。我初始化数组的方式是前 5 个单元格的值非常接近允许的最大值,而其他五个单元格的值远离最大值。
我决定为此使用全局互斥锁和条件变量。在 main
中,首先生成 10 个加倍线程,然后生成另外 10 个减半线程。但后来我的程序冻结了。我不明白问题是什么,感谢任何帮助。
我的动机是更好地理解 pthreads 和条件变量。
这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <ntsid.h>
#include <pthread.h>
#include <unistd.h>
#define MAX 20
#define THREADS_NUM 10
#define OFFSET 10
typedef struct myStruct {
int cellId;
} myStruct;
int * cells;
pthread_mutex_t globalMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t globalCond = PTHREAD_COND_INITIALIZER;
pthread_t threads[THREADS_NUM * 2];
void * DoublerThread(void * arg) {
myStruct * myStr = (myStruct *) arg;
int id = myStr->cellId;
pthread_mutex_t mutex = globalMutex;
pthread_cond_t condition = globalCond;
pthread_mutex_lock(&mutex);
while((cells[id] * 2) > MAX) {
printf("Waiting... id = %d\n", id);
pthread_cond_wait(&condition, &mutex);
}
cells[id] *= 2;
printf("new val = %d, id = %d\n", cells[id], id);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void * HalverThread(void * arg) {
myStruct * myStr = (myStruct *) arg;
int id = myStr->cellId;
pthread_mutex_t mutex = globalMutex;
pthread_cond_t condition = globalCond;
sleep(1);
pthread_mutex_lock(&mutex);
cells[id] /= 2;
pthread_cond_broadcast(&condition);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void initMyStructs(myStruct ** myStructs) {
int i;
for(i = 0; i < THREADS_NUM * 2; i++) {
myStructs[i] = (myStruct *) malloc(sizeof(myStruct) * 2);
if(!myStructs[i]) {
printf("malloc error\n");
exit(EXIT_FAILURE);
}
myStructs[i]->cellId = i % THREADS_NUM;
}
}
void initCells() {
int i, tmp;
cells =(int *) malloc(sizeof(int));
if(!cells) {
printf("malloc error\n");
exit(EXIT_FAILURE);
}
for(i = 0; i <= THREADS_NUM; i++) {
if(i < THREADS_NUM / 2) {
cells[i] = MAX - 1;
} else {
tmp = cells[i] = 1;
}
}
}
int main() {
int i;
myStruct ** myStructs;
initMyStructs(myStructs);
initCells();
//create 10 Doubler threads
for(i = 0; i < THREADS_NUM; i++) {
pthread_create(&threads[i], NULL, DoublerThread, (void *) myStructs[i]);
}
//create 10 Halver threads
for(i = 0; i < THREADS_NUM; i++) {
pthread_create(&threads[i + OFFSET], NULL, HalverThread, (void *) myStructs[i + OFFSET]);
}
for(i = 0; i < THREADS_NUM + OFFSET; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
您为每个线程创建了“私有”互斥锁和条件变量,因此它们没有以任何(有意义的)方式同步。而不是这个:
pthread_mutex_t mutex = globalMutex;
pthread_cond_t condition = globalCond;
只需使用 globalMutex 和 globalCond -- 这就是您真正想要的。
[
我把它移到这里,因为我认为我们应该这样做。我无法直觉如此礼节。
]
By the way, just to make sure I understand this, the mutex is per
cell, so that multiple threads can work on multiple cells
simultaneously, right? Just not two threads on the same cell. –
所以,您可能想要的是:
typedef struct myStruct {
int cellId;
pthread_mutex_t lock;
pthread_cond_t wait;
} myStruct;
并在 InitMyStruct() 中:
myStructs[i]->cellId = i % THREADS_NUM;
pthread_mutex_init(&myStructs[i]->lock, NULL);
pthread_cond_init(&myStructs[i]->wait, NULL);
在减半中:
pthread_mutex_lock(&myStr->lock);
cells[id] /= 2;
pthread_cond_broadcast(&myStr->wait);
pthread_mutex_unlock(&myStr->lock);
和加倍器:
...
pthread_mutex_lock(&myStr->lock);
while((cells[id] * 2) > MAX) {
printf("Waiting... id = %d\n", id);
pthread_cond_wait(&myStr->wait, &myStr->lock);
}
cells[id] *= 2;
printf("new val = %d, id = %d\n", cells[id], id);
pthread_mutex_unlock(&myStr->lock);
So currently, only one thread can make changes to the array at a time?
But then the program exits after about a second, if threads couldn't
be making changes to the array simultaneously then wouldn't the
program take 10 seconds to finish, because each HalverThread sleeps
for 1 second. – Yos 6 hours
Halvers 在抢到 mutex 之前睡眠,因此所有的 sleep 都在附近同时,醒来,争夺 mutex 并继续。
我在 C 中使用 pthreads 以便对 int
数组执行两个操作:一个操作将单元格的值加倍,另一个操作将单元格的值减半。如果在将单元格加倍后,其值将变得大于线程需要等待的最大允许值,直到另一个线程将该单元格的值减半。我初始化数组的方式是前 5 个单元格的值非常接近允许的最大值,而其他五个单元格的值远离最大值。
我决定为此使用全局互斥锁和条件变量。在 main
中,首先生成 10 个加倍线程,然后生成另外 10 个减半线程。但后来我的程序冻结了。我不明白问题是什么,感谢任何帮助。
我的动机是更好地理解 pthreads 和条件变量。
这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <ntsid.h>
#include <pthread.h>
#include <unistd.h>
#define MAX 20
#define THREADS_NUM 10
#define OFFSET 10
typedef struct myStruct {
int cellId;
} myStruct;
int * cells;
pthread_mutex_t globalMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t globalCond = PTHREAD_COND_INITIALIZER;
pthread_t threads[THREADS_NUM * 2];
void * DoublerThread(void * arg) {
myStruct * myStr = (myStruct *) arg;
int id = myStr->cellId;
pthread_mutex_t mutex = globalMutex;
pthread_cond_t condition = globalCond;
pthread_mutex_lock(&mutex);
while((cells[id] * 2) > MAX) {
printf("Waiting... id = %d\n", id);
pthread_cond_wait(&condition, &mutex);
}
cells[id] *= 2;
printf("new val = %d, id = %d\n", cells[id], id);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void * HalverThread(void * arg) {
myStruct * myStr = (myStruct *) arg;
int id = myStr->cellId;
pthread_mutex_t mutex = globalMutex;
pthread_cond_t condition = globalCond;
sleep(1);
pthread_mutex_lock(&mutex);
cells[id] /= 2;
pthread_cond_broadcast(&condition);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void initMyStructs(myStruct ** myStructs) {
int i;
for(i = 0; i < THREADS_NUM * 2; i++) {
myStructs[i] = (myStruct *) malloc(sizeof(myStruct) * 2);
if(!myStructs[i]) {
printf("malloc error\n");
exit(EXIT_FAILURE);
}
myStructs[i]->cellId = i % THREADS_NUM;
}
}
void initCells() {
int i, tmp;
cells =(int *) malloc(sizeof(int));
if(!cells) {
printf("malloc error\n");
exit(EXIT_FAILURE);
}
for(i = 0; i <= THREADS_NUM; i++) {
if(i < THREADS_NUM / 2) {
cells[i] = MAX - 1;
} else {
tmp = cells[i] = 1;
}
}
}
int main() {
int i;
myStruct ** myStructs;
initMyStructs(myStructs);
initCells();
//create 10 Doubler threads
for(i = 0; i < THREADS_NUM; i++) {
pthread_create(&threads[i], NULL, DoublerThread, (void *) myStructs[i]);
}
//create 10 Halver threads
for(i = 0; i < THREADS_NUM; i++) {
pthread_create(&threads[i + OFFSET], NULL, HalverThread, (void *) myStructs[i + OFFSET]);
}
for(i = 0; i < THREADS_NUM + OFFSET; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
您为每个线程创建了“私有”互斥锁和条件变量,因此它们没有以任何(有意义的)方式同步。而不是这个:
pthread_mutex_t mutex = globalMutex;
pthread_cond_t condition = globalCond;
只需使用 globalMutex 和 globalCond -- 这就是您真正想要的。
[ 我把它移到这里,因为我认为我们应该这样做。我无法直觉如此礼节。 ]
By the way, just to make sure I understand this, the mutex is per cell, so that multiple threads can work on multiple cells simultaneously, right? Just not two threads on the same cell. –
所以,您可能想要的是:
typedef struct myStruct {
int cellId;
pthread_mutex_t lock;
pthread_cond_t wait;
} myStruct;
并在 InitMyStruct() 中:
myStructs[i]->cellId = i % THREADS_NUM;
pthread_mutex_init(&myStructs[i]->lock, NULL);
pthread_cond_init(&myStructs[i]->wait, NULL);
在减半中:
pthread_mutex_lock(&myStr->lock);
cells[id] /= 2;
pthread_cond_broadcast(&myStr->wait);
pthread_mutex_unlock(&myStr->lock);
和加倍器: ...
pthread_mutex_lock(&myStr->lock);
while((cells[id] * 2) > MAX) {
printf("Waiting... id = %d\n", id);
pthread_cond_wait(&myStr->wait, &myStr->lock);
}
cells[id] *= 2;
printf("new val = %d, id = %d\n", cells[id], id);
pthread_mutex_unlock(&myStr->lock);
So currently, only one thread can make changes to the array at a time? But then the program exits after about a second, if threads couldn't be making changes to the array simultaneously then wouldn't the program take 10 seconds to finish, because each HalverThread sleeps for 1 second. – Yos 6 hours
Halvers 在抢到 mutex 之前睡眠,因此所有的 sleep 都在附近同时,醒来,争夺 mutex 并继续。