MIT6.828 operating system:Threads and Locking

report of Threads and Locking

文章目录

  • report of Threads and Locking
    • 实验要求
    • 实验了解
      • 初步了解
      • 问题探究
    • 实验过程

实验要求

threads and locking

实验了解

初步了解

在我们使用gcc -g -O2 ph.c -pthread成功编译后,按照实验指导书我们体会一下单线程和双线程的区别

harry@ubuntu:~/Desktop/os/Threads and Locking$ ./a.out 1
0: put time = 0.004051
0: get time = 6.730206
0: 0 keys missing
completion time = 6.734654

harry@ubuntu:~/Desktop/os/Threads and Locking$ ./a.out 2
1: put time = 0.009607
0: put time = 0.010374
1: get time = 6.664562
1: 14969 keys missing
0: get time = 6.673753
0: 14969 keys missing
completion time = 6.684481

每个线程分两个阶段(phases)运行。在第一个阶段,每个线程将NKEYS/nthread keys放入the hash table
在第二阶段,每个线程从散列表中获取NKEYSprint语句告诉你每个阶段为每个线程花费了多长时间。
倒数第二行会告诉你有多少个key丢失了,底部的completion time告诉你应用程序的总运行时间。

原理:

#define NBUCKET 5
#define NKEYS 100000

ph.c程序主要工作是使用随机数生成10000个keys,然后利用线性hash将其插入5个哈希槽中,最后再取出每个key

问题探究

两个发现:
(1)通过以上单个线程和双线程我们可以分析得到,双线程完成的工作是单线程的二倍,但是时间上很接近,
(2)就是在单线程运行时key的丢失为0,而双线程时对于key的丢失时很严重的.

两个问题
(1)为什么双线程会丢失大量的key?而单线程时不会
在用户没有设定线程间的调度策略时,系统默认采取基于时间片轮转的调度策略。所以当NKEYS=100000时,会出现两个线程的多次轮转,也才有可能导致key的丢失。
具体过程是当thread1刚进入insert()还未进行插入时,轮转到另一个线程2进行了插入。回到线程1,此时的n还是为空,再进行连接时,就会丢失掉线程2插入的表项。
说白了就是当第一个thread还未插入key时,另一个thread的key覆盖了原来key,所以导致了第一个线程key的丢失。
当我们把NKEYS改成10的时候,就算不用put里也不加锁,也并没有丢失任何key,说明了这一点。

(2)为什么同样的代码执行的线程会不一样?下面是我某两次实验的结果

harry@ubuntu:~/Desktop/os/Threads and Locking$ ./a.out 2
0: put time = 0.007914
1: put time = 0.008186
0: get time = 6.571305
0: 1672 keys missing
1: get time = 6.612520
1: 1477 keys missing
completion time = 6.622177
harry@ubuntu:~/Desktop/os/Threads and Locking$ ./a.out 2
1: put time = 0.016394
0: put time = 0.020926
1: get time = 7.242295
1: 2121keys missing
0: get time = 7.336555
0: 2023 keys missing
completion time = 7.358044

答:一开始,应该是在主线程里,然后主线程因为pthread_join而要等线程0和线程1结束。然后线程0与线程1都开始put,因为__sync_fetch_and_add需要等所有线程完成put操作,所以先完成put操作的子线程会print出put的时间然后阻塞等另一个线程完成put操作。然后再通过get来遍历哈希表。所以顺序不一样应该是正常的,看哪边先put完,跟机器应该也有关系。
所以线程的顺序不一样没有关系
感谢这位大佬对这个问题的解释

实验过程

通过以上我们了解到为了避免双线程丢失大量key的发生,在put和get中插入lock和unlock语句,使得丢失的键数总是0。
修改ph.c的代码内容如下:

//首先在开始处定义一个五个互斥锁
pthread_mutex_t bucket_locks[NBUCKET];  //五个是因为有五个存放key的桶,每一个都需要在使用时上锁
//然后再在put函数中加锁和解锁:
static 
void put(int key, int value)
{
  
  int i = key % NBUCKET;
  pthread_mutex_lock(&bucket_locks[i]);  
  //上锁
  insert(key, value, &table[i], table[i]);
  pthread_mutex_unlock(&bucket_locks[i]);
  //解锁
}

然后我们检查一下就可以发现结果正确

harry@ubuntu:~/Desktop/os/Threads and Locking$ ./a.out 2
1: put time = 0.008080
0: put time = 0.008928
0: get time = 6.399594
0: 0 keys missing
1: get time = 6.400445
1: 0 keys missing
completion time = 6.410268

我们的实验到这也就完成了

你可能感兴趣的:(os,MIT,Threads,and,Locking,os,xv6)