一.
通过根据README里提供的指令,输出之后会发现,当只采用一个线程的时候,不会发生key的丢失,但是当使用两个线程的时候,会发生丢失的情况,开始看代码。
在main函数里,首先根据参数获取线程数,然后会随机生成数,赋值给keys数组,之后对输入的线程数生成相应的线程,使用create函数,在里面有一个thread参数,阅读代码
此时,已经有多个线程了,首先看put函数
最开始没有锁,会发现,put函数的作用就是对keys数组的每个key,并取i为key%NBUCKET,这其实是一个哈希表,将其插入table【i】位置的链表中,是哈希表中处理冲突的连地址法,可以保证对相同的i,可以存入同一个位置。看到这里可以明白,如果是两个线程的话,有可能会对同一个table【i】同时进行insert,可能导致某些key没有插入成功从而导致丢失。首先简单的方法就是对table设一个锁,但是table是一个链表数组,显然这样是低效的,所以对每一个链表设置锁就可以。可以看到在main函数里,对每个锁进行了初始化。
第一个实验就此完成。
二.
可以看到有一个Assertion failed: (i == t),说明 这里i!=t,查看代码。
main函数大体相似,直接看thread
bstate是给定的结构体。
这是最初的barrier函数,可以看出只是简单的对round++,为什么会i!=t呢,因为有多线程,可能有的线程进行的快,一个线程在i=1的时候,另一个线程可能已经把round增长到10了,所以会断言错误。
根据readme提供的wait 和 broadcast,可以想到一种思路,当每个线程走完一轮后,先停下,等待所有线程进行完成,之后进行下一轮。
可以看到在bstate结构体里,还贴心的注释了Number of threads that have reached this round of the barrier。
在barrier函数里,首先lock一个锁,因为要进行nthread的操作,如果当前线程不是最后一个线程,就会使当前线程wait,wait会释放锁,此时其他线程可以运行,一直到最后一个线程,他会调用broadcast唤醒所有线程,并把nthread设为0,并且最后要unlock,应为唤醒后,会自动地加上锁,所以需要unlock
成功通过。