我正在阅读《 Unix环境下的高级编程》一书中的Thread Synchronization

In this section,有一个示例可以将互斥体与动态分配的对象一起使用。我也有同样的疑问。

在这里,我分享了一个事件时间表(从上到下),以解释我的疑问:

  • Thread1已创建。
  • Thread1创建一个互斥锁var对其进行初始化,并将其放在全局列表中,以便其他人可以使用它。
  • 现在Thread1获得了一个锁,可以使用共享数据结构ds。线程1需要使用ds进行大量工作,即线程1将长时间获取此锁。
  • 现在,尽管Thread1仍然获得了锁,但创建了Thread2。
  • 现在Thread2也想使用ds。
  • 因此,Thread2必须首先递增计数器,以显示对ds的引用增加了。为此(根据本书),首先需要使用相同的mutex_t变量获取锁,然后再增加计数。
  • 但是,因为Thread1已经获得了对该mutex_t变量的锁定,所以当Thread2在递增计数之前调用lock()时,它将不得不等到Thread1解锁该锁定。

  • 怀疑:
  • 关于他正在谈论哪个全局列表(仅用于创建任何列表并将其引用传递给所有线程或任何特定列表)?
  • 当Thread1创建lock变量时,将其计数设置为1。然后Thread2正在等待将该计数增加为2。但是,假设在完成当前工作后Thread1不需要使用ds的情况。因此,在解锁之前,请先减少计数或先对其进行解锁,然后再调用foo_rele()以再次锁定并减少计数。现在有可能在Thread2递增计数之前,Thread1递减计数。如果是(根据我),那么我的数据结构将被破坏?因此,我认为这本书的示例存在一些错误。如果我们使用不同的mutex_var来增加计数会更好吗?
  • 最佳答案

    答:我认为在术语“全局列表”下,作者理解线程之间共享的所有变量。

    例子:

    struct foo* shared_foo; /* This pointer is shared between all threads */
    
    struct foo* foo_alloc(void)
    {
       /* This pointer is local to the thread which allocates the memory */
       struct foo *fp;
    
        if ((fp = malloc(sizeof(struct foo))) != NULL) {
            /* whatever */
        }
        /* local pointer value returned */
        return(fp);
    }
    
    /* probably somewhere in the code the shared pointer (on the 'global list') is initialized this way */
    shared_foo = foo_alloc();
    

    B.嗯...我真的不理解你说的话。你能把你的情况写成一个 list 吗?我认为f_count在初始化过程中被设置为标志“此互斥体正在使用”。因此,当互斥锁释放时,f_count值设置为1。当Thread1获取锁时,其值设置为2。当释放锁时,该值重新设置为1。有效的f_count值是:1(初始化并免费) )和2(已初始化且处于忙碌状态)。为了释放该互斥锁,您只需要在获取时调用两次foo_rele(f_count = 2),或在空闲时调用一次(f_count = 1)。然后f_count值达到0,并且互斥量被删除。

    09-30 12:23