使用没有互斥锁的线程增加全局变量奇怪地 returns 正确值
Incrementing the global variable using threads without a mutex strangely returns correct value
我们被要求创建 4 个线程,每个线程递增(SPIN
/4 倍)全局变量 compteur
的值,据说每个线程都是 accessing/changing 全局变量在另一个完成迭代之前(这就是为什么 SPIN
被赋予一个非常大的数字),例如线程号 1 首先访问 compteur
并且当它递增另一个线程访问 compteur 并看到 compteur = 0
仍然,最后得出结论,我们必须使用 MUTEX。
问题是程序总是在不应该的情况下给我与 SPIN 相同的值。
你能解释一下为什么吗?
#define SPIN 40000000
int compteur = 0;
void *routine_thread(void *arg) {
int i;
printf("accessing thread ... \n");
for (i = 0; i < SPIN / 4; ++i) {
compteur++;
}
printf("quitting thread ... \n");
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_t thread_id[4];
void *resultat_thread;
int statut;
int i;
for (i = 0; i < 4; i++) {
statut = pthread_create(&thread_id[i], NULL, routine_thread, NULL);
if (statut != 0) {
fprintf(stderr, "error creating thread\n");
exit(EXIT_FAILURE);
}
statut = pthread_join(thread_id[i], &resultat_thread);
if (statut != 0) {
fprintf(stderr, "error joining the thread\n");
exit(EXIT_FAILURE);
}
}
printf("compteur value is : %d\n", compteur);
if (resultat_thread == NULL)
return EXIT_FAILURE;
else
return EXIT_SUCCESS;
}
当你在循环中调用pthread_join
时,主线程处于空闲状态,等待另一个线程退出。因此,您将获得如下工作流程:
Run thread 0
Wait for thread 0
Thread 0 exited
Run thread 1
Wait for thread 1
Thread 1 exited
...
没有线程同时 运行。
您应该将 运行 线程循环和等待线程循环分开。
for(i= 0; i< 4; i++) {
statut = pthread_create(&thread_id[i], NULL, routine_thread, NULL);
if(statut != 0) {
fprintf(stderr, "error creating thread\n");
exit(EXIT_FAILURE);
}
}
for(i= 0; i< 4; i++) {
statut = pthread_join(thread_id[i], &resultat_thread);
if(statut != 0) {
fprintf(stderr, "error joining the thread\n");
exit(EXIT_FAILURE);
}
}
您已经序列化了正在创建的线程。 pthread_join()
循环内部调用等待线程完成,然后再创建下一个线程。
因此,您在任何时候都只有一个线程处于活动状态(主线程除外),它会修改 compteur
。所以没有 data race 您期望观察到的结果。
从循环中删除 pthread_join
调用。并创建另一个循环来等待线程:
for(i= 0; i< 4; i++) {
statut = pthread_join(thread_id[i], NULL);
if(statut != 0) {
fprintf(stderr, "error joining the thread\n");
exit(EXIT_FAILURE);
}
}
您的线程函数没有 return 任何值。因此,您可以在 pthread_join
调用中使用 NULL
而不是 &resultat_thread
。
for(i= 0; i< 4; i++) {
statut = pthread_create(&thread_id[i], NULL, routine_thread, NULL);
if(statut != 0){
fprintf(stderr, "error creating thread\n");
exit(EXIT_FAILURE);
}
statut = pthread_join(thread_id[i], &resultat_thread);
if(statut != 0){
fprintf(stderr, "error joining the thread\n");
exit(EXIT_FAILURE);
}
}
此代码创建一个线程并等待线程完成它 execution.so 全局变量 compteur
将被线程访问一次,这就是为什么你每次都获得相同的值。
要实现objective所有线程的增量(SPIN/4倍)全局变量compteur
的值同时你应该先创建所有4个线程pthread_create()
然后调用pthread_join()
等待
我们被要求创建 4 个线程,每个线程递增(SPIN
/4 倍)全局变量 compteur
的值,据说每个线程都是 accessing/changing 全局变量在另一个完成迭代之前(这就是为什么 SPIN
被赋予一个非常大的数字),例如线程号 1 首先访问 compteur
并且当它递增另一个线程访问 compteur 并看到 compteur = 0
仍然,最后得出结论,我们必须使用 MUTEX。
问题是程序总是在不应该的情况下给我与 SPIN 相同的值。
你能解释一下为什么吗?
#define SPIN 40000000
int compteur = 0;
void *routine_thread(void *arg) {
int i;
printf("accessing thread ... \n");
for (i = 0; i < SPIN / 4; ++i) {
compteur++;
}
printf("quitting thread ... \n");
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_t thread_id[4];
void *resultat_thread;
int statut;
int i;
for (i = 0; i < 4; i++) {
statut = pthread_create(&thread_id[i], NULL, routine_thread, NULL);
if (statut != 0) {
fprintf(stderr, "error creating thread\n");
exit(EXIT_FAILURE);
}
statut = pthread_join(thread_id[i], &resultat_thread);
if (statut != 0) {
fprintf(stderr, "error joining the thread\n");
exit(EXIT_FAILURE);
}
}
printf("compteur value is : %d\n", compteur);
if (resultat_thread == NULL)
return EXIT_FAILURE;
else
return EXIT_SUCCESS;
}
当你在循环中调用pthread_join
时,主线程处于空闲状态,等待另一个线程退出。因此,您将获得如下工作流程:
Run thread 0
Wait for thread 0
Thread 0 exited
Run thread 1
Wait for thread 1
Thread 1 exited
...
没有线程同时 运行。
您应该将 运行 线程循环和等待线程循环分开。
for(i= 0; i< 4; i++) {
statut = pthread_create(&thread_id[i], NULL, routine_thread, NULL);
if(statut != 0) {
fprintf(stderr, "error creating thread\n");
exit(EXIT_FAILURE);
}
}
for(i= 0; i< 4; i++) {
statut = pthread_join(thread_id[i], &resultat_thread);
if(statut != 0) {
fprintf(stderr, "error joining the thread\n");
exit(EXIT_FAILURE);
}
}
您已经序列化了正在创建的线程。 pthread_join()
循环内部调用等待线程完成,然后再创建下一个线程。
因此,您在任何时候都只有一个线程处于活动状态(主线程除外),它会修改 compteur
。所以没有 data race 您期望观察到的结果。
从循环中删除 pthread_join
调用。并创建另一个循环来等待线程:
for(i= 0; i< 4; i++) {
statut = pthread_join(thread_id[i], NULL);
if(statut != 0) {
fprintf(stderr, "error joining the thread\n");
exit(EXIT_FAILURE);
}
}
您的线程函数没有 return 任何值。因此,您可以在 pthread_join
调用中使用 NULL
而不是 &resultat_thread
。
for(i= 0; i< 4; i++) {
statut = pthread_create(&thread_id[i], NULL, routine_thread, NULL);
if(statut != 0){
fprintf(stderr, "error creating thread\n");
exit(EXIT_FAILURE);
}
statut = pthread_join(thread_id[i], &resultat_thread);
if(statut != 0){
fprintf(stderr, "error joining the thread\n");
exit(EXIT_FAILURE);
}
}
此代码创建一个线程并等待线程完成它 execution.so 全局变量 compteur
将被线程访问一次,这就是为什么你每次都获得相同的值。
要实现objective所有线程的增量(SPIN/4倍)全局变量compteur
的值同时你应该先创建所有4个线程pthread_create()
然后调用pthread_join()
等待