我有这个功课到学校 - 我完成它发送它并得到0%:] ... 所以我想问一下我的想法是否正确。例如,如果我想用线程编写程序 - 我必须调用50次thrfunction并且我有5个线程可用(我必须尽可能多地使用它们)。你能否告诉我,如果我做错了什么 - 我猜我是因为printf说我只使用一个线程?我不太确定我会做这件事的方法。
提前致谢 NikolasJíša
这是我的源代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define THREADS 5
#define CYCLES 50
sem_t sem1;
pthread_mutex_t m1, m2;
long int result = 0;
int thread_status[THREADS]; // status of threads, value -1 for working thread, other values for free threads
typedef struct Arg {
long int number;
int thread_ID; } ARG;
void * thrfunction ( void * arg ) {
int number = (( ARG * ) arg)->number, thread_ID = (( ARG * ) arg)->thread_ID, i;
thread_status[thread_ID] = -1;
pthread_mutex_unlock ( & m1 );
for ( i = 0; i < number; i ++ );
pthread_mutex_lock ( & m2 );
result = result + number;
printf ( "Thread %d result = %ld\n", thread_ID, result );
pthread_mutex_unlock ( & m2 );
pthread_mutex_lock ( & m1 );
thread_status[thread_ID] = thread_ID;
sem_post ( & sem1 );
pthread_mutex_unlock ( & m1 );
return NULL; }
int main ( int argc, char * argv[] ) {
pthread_t thr[THREADS];
pthread_attr_t Attr; pthread_attr_init ( & Attr ); pthread_attr_setdetachstate ( & Attr, PTHREAD_CREATE_JOINABLE );
pthread_mutex_init ( & m1, NULL ); pthread_mutex_init ( & m2, NULL );
sem_init ( & sem1, 0, THREADS );
int i, j;
ARG * pom = ( ARG * ) malloc ( sizeof ( * pom ) );
for ( i = 0; i < THREADS; i ++ )
thread_status[i] = i;
for ( i = 0; i < CYCLES; i ++ ) {
pom->number = rand () % 100000 * 10000;
sem_wait ( & sem1 );
pthread_mutex_lock ( & m1 );
for ( j = 0 ; j == -1; j ++ );
pthread_create ( & thr[j], & Attr, thrfunction, ( void * ) pom ); }
free ( pom );
pthread_attr_destroy ( & Attr ); pthread_mutex_destroy ( & m1 ); pthread_mutex_destroy ( & m2 ); sem_destroy ( & sem1 );
for ( i = 0; i < THREADS; i ++ )
pthread_join ( thr[i], NULL );
return 0;}
答案 0 :(得分:2)
我看到的第一个问题是你经常使用锁 。
如果所有程序都采用锁定,则线程编程的效率远低于顺序编程。锁定需要花费时间来获取和释放。那段时间将从你的计划应该做的工作中消失。
我看到的第二个问题是for
中的thrfunction
循环什么也没做。它计算从0到数字?这就是全部吗?
我看到的第三个问题是你调用free(pom)
并在创建所有线程后调用pthread_mutex_destroy
。 坏!线程仍在使用它!您无法保证线程甚至已经开始在此时运行。您的操作系统可能需要几秒钟甚至几分钟(如果RAM很低并且交换到磁盘)以开始运行您创建的所有线程。
你可能会发现有关思考线程的一些事情是写下每个“关键部分”,锁之间的部分,卡片上,或使用任何可移动的代表那些部分。为每个线程制作一些卡片或片段。除非锁,连接,信号量或其他任何东西阻止它,否则这些碎片可以在时间轴中向上或向下移动。如果你想获得真正的技术,编译器优化和处理器乱序执行甚至可以在限制范围内重新安排件执行顺序。
某些程序(不是你的程序)可能如下所示(并查看步骤7中线程如何在锁定速度减慢到单速):
0 <- parent process spawns threads
1 <- parent process calls join to wait for thread in first column.
2 2 2
3 3
4 3 4
5 5 2
6 6 3
4
5
6
7 4 7 7 <-- step 7 waits for lock
5 8
6 9
7 10
11 <- step 11 releases lock
8
9
10
11
8
9
10
11
8
9
10
11
12 12 12 12
13 13 13 13
14 14 14 14 <- step 14 each thread returns.
15 <- parent process wait on thread 1 succeeds.
16 <- wait for thread 2
17 <- wait for thread 3
18 <- wait for thread 4
19 <- parent now cleans up thread data, lock data.
20 <- parent exits.