MIT6.828 Homework6:Threads and Locking

文章讨论了在put和get函数中插入lock和unlock语句以防止丢失密钥的问题。实验表明,适当的锁机制可以避免并发时的数据竞争,但过度的锁定会增加完成时间。最终,作者优化了锁策略,使用bucket级互斥锁实现并行put操作,确保正确性和效率。
摘要由CSDN通过智能技术生成

实验任务:

Insert lock and unlock statements in put and get so that the number of keys missing is always 0.

在put和get函数中插入lock和unlock语句,以便丢失的密钥数始终为0。

实验内容:

未插入lock和unlock语句时

$ gcc -g -O2 ph.c -pthread

$ ./a.out 2

运行命令得到以下结果

每个线程分两个阶段运行。在第一阶段,每个线程将NKEYS/nthread键放入哈希表中。在第二阶段,每个线程从哈希表中获取NKEYS。

$ ./a.out 1

再运行命令

可以看出,单线程与双线程完成时间大概相同,但是双线程做了两次get keys操作有效实现了并行;双线程会发生keys missing的情况。

查看代码分析出put key时调用insert函数时,会将新的entry插入到链表的头部,即修改链表头部指针,导致错误。

put和get中插入lock和unlock语句如下

pthread_mutex_t lock;     // declare a lock

// pthread_mutex_init(&lock, NULL);   // initialize the lock

// pthread_mutex_lock(&lock);  // acquire lock

// pthread_mutex_unlock(&lock);  // release lock

static

void put(int key, int value)

{

  pthread_mutex_lock(&lock);  // acquire lock

  int i = key % NBUCKET;

  insert(key, value, &table[i], table[i]);

  pthread_mutex_unlock(&lock);  // release lock

}

static struct entry*

get(int key)

{

  //pthread_mutex_lock(&lock);  // acquire lock

  struct entry *e = 0;

  for (e = table[key % NBUCKET]; e != 0; e = e->next) {

    if (e->key == key) break;

  }

  //pthread_mutex_unlock(&lock);  // release lock

  return e;

}

再次进行测试

可以看到双线程key不再丢失,代码正确,但是完成时间变长了。

再次查看get部分代码,发现get操作并未涉及到修改hash表,即

只有读取操作,所以可以不用进行锁保护,所以我们取消get部分的锁,再次运行:

static struct entry*

get(int key)

{

  // pthread_mutex_lock(&lock);  // acquire lock

  struct entry *e = 0;

  for (e = table[key % NBUCKET]; e != 0; e = e->next) {

    if (e->key == key) break;

  }

  // pthread_mutex_unlock(&lock);  // release lock

  return e;

}

可以看到双线程仍然可以正确运行,且完成时间缩短。

再尝试对put中每一个bucket上锁,仍能正确运行。

pthread_mutex_t lock[NBUCKET];

static

void put(int key, int value)

{

  int i = key % NBUCKET;

  pthread_mutex_lock(&lock[i]);

  insert(key, value, &table[i], table[i]);

  pthread_mutex_unlock(&lock[i]);

}

此时每个bucket都有一个互斥锁,当执行put操作时,首先获取待处理bucket的锁,然后在完成后释放锁。 这允许同时访问不同的bucket而不会相互冲突,可以使put操作在保持正确性的同时并行运行。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值