C语言,Linux,线程

clverjame 发布于 2012/03/22 12:40
阅读 1K+
收藏 2
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
// repeat 100 times to mimic 100 random visits to the page
#define RPT 100
//web page visit counter
int cnt=0;
void* counter() {
int cntLocalCopy;
float r;
cntLocalCopy = cnt;
// mimicking the work of the sever in serving the page to
// the browser
r = rand() % 2000; usleep(r);
cnt = cntLocalCopy + 1;
}
int main () {
int i;
float r;
pthread_t tid[RPT];
// seed the random number sequence
srand(time(NULL));
for (i=0; i<RPT; i++) {
// mimicking the random access to the web page
r = rand() % 2000; usleep(r);
// a thread to respond to a connect from a browser
pthread_create (&tid[i], NULL, &counter, NULL);
}
// Wait till threads complete.
for (i=0; i<RPT; i++) {
pthread_join(tid[i], NULL);
}
// print out the counter value and the number of mimicked visits
// the 2 values should be the same if the program is written
// properly
printf ("cnt=%d, repeat=%d\n", cnt, RPT);
}

输出:

cnt=63, repeat=100
cnt=59, repeat=100
cnt=58, repeat=100
cnt=63, repeat=100
cnt=59, repeat=100
cnt=59, repeat=100

这好像是一个关于统计网站浏览的题。但看不懂。求解读。我把程序在linux下编译不过。说没有定义'pthread_create'跟'pthread_join'

加载中
0
Yisen
Yisen
你把 cntLocalCopy = cnt;这句话放到
r =  rand () % 2000; usleep(r);这句下面试试
c
clverjame
我把*Count()里的cntLocalCopy=cnt;放到了usleep...;这后面了。后面执行后每次cnt每次就等于100了。正确的效果应该是这样的吗
Yisen
Yisen
@clverjaem : counter里面的
c
clverjame
这里头有两个这句话,一个是在main函数里的。一个是在 *counter函数里的。是指哪个呢
0
Yisen
Yisen
编译加上-lpthread
c
clverjame
还是一样不行。我的文件名为t2 gcc - t2 t2.c -Ipthread是这样吗
0
Yisen
Yisen

是小写的L,-lpthread

gcc -o t2 t2.c -lpthread

c
clverjame
我已经可以运行了。你可以告诉我为什么每次的cnt输出都不一样吗
0
海子IT

应该是

gcc- o t2 t2.c -pthread

0
Yisen
Yisen
因为每个线程先读cnt,然后usleep一小段时间,可能这睡眠的时间内,其他线程操作改变了cnt的值,但是睡醒后还是按原来的值+1赋值,所以每次都可能会不一样
c
clverjame
我试了很多次输出,大概输出就在74-85之间。为什么这个值不会一直增加下去
0
中山野鬼
中山野鬼

引用来自“yisen”的答案

你把 cntLocalCopy = cnt;这句话放到
r =  rand () % 2000; usleep(r);这句下面试试

这个是正解。 cnt是个类似互斥量的东西。 原则上说。多个进程对同一个变量进行修改,一定需要按照原子操作的的方式进行。这里并不是说不允许其他进程打算自己的操作。但至少要存在一个对上述变量的锁操作。以防止其他进程改写。

正确的做法是需要用pthread_mutex 之类的东西,当然实现方法不是就这一种,将变量保护起来。如果其他进程发现数据被锁住则被堵塞。

c
clverjame
把它放进去后有什么好久吗,现在程序是哪里不妥或者说是哪里有缺陷。麻烦您再跟我说一下好吗
0
晓寒
晓寒
你这里的随机数基本没有起作用,我不知道你为什么在主函数里放个随机数,还在couter里也有随机数, 你可以把随机数打印出来就会发现,都是一样的,另外,在couter里对临界资源cnt的使用也没有保护。参见楼上的回答内容。可以看出,你对于多线程这块还比较陌生,应该多在这些基础上下些功夫,上面说的东西大部分都是多线程情况下基本的和常用的东西。
c
clverjame
我还真不了解多线程。这个学期我才第一次接解线程。我以前学生物的,我学线程给我的感觉就是DNA在染色体上的东西。这代码是我老师给的,他意在让我们修改这个代码,让它变成更合理。可是我连这代码想干什么都不懂。
0
中山野鬼
中山野鬼

@clverjaem


你现在的代码会出现这样的问题。假设你的代码已经调整成如下:

int cnt=0;
08	void* counter() {
09	
10	float r;
11	
12	// mimicking the work of the sever in serving the page to
13	// the browser
14	r = rand() % 2000; usleep(r);
15	cnt = cnt + 1;
16	}

上面这样已经都快了。读了就加,加了就写出。

 ld a0,[cnt]
 inc a0,a0
 st [cnt],a0

上面是对应的伪汇编,但是如果在st[cnt],a0没有被执行前,这个进程被挂起,让给别的进程操作,

那么此时,别的进程读到的,仍然是这个进程没有+1的cnt值,假设是 59.

那么新进来的进程会对cnt写60进去。而当前进程,由于重新获得CPU的控制权,继续运行,而a0里面也是60,59+1出来的。此时就出现,两个进程,均读取的是59,而均写出60的情况,此时cnt就不能反应有多少次不同进程被调用的数据。

 

 

0
Yisen
Yisen

这段代码不合理的地方就在于线程不安全,也就是共享的变量没有保护。

你先读取了全局变量cnt的值,然后usleep了一小段时间,再去修改cnt的值
这中间睡眠了一段时间,有可能其他线程已经修改了cnt的值。

老师要你们改,简单的做法就是上面说的先睡再改,高级点得做法就是加锁

c
clverjame
@clverjaem : 是的。我刚刚也是发现代码中有一个循环100次的。谢谢你
c
clverjame
为什么修改后仍然没有看到效果。输出都是100。应该是可以看到增加的次数吗。因为这个代码好像是统计访问量
c
clverjame
原来是这样呀。谢谢。您们都是神哥,都是编程帝。
0
c
clverjame
有没有一个代码例子是两个线程共享一个资源,并让它们列锁。也就是说求这一程序代码(C语言初学者)。thx
返回顶部
顶部