0

我对 Linux 编程很陌生,所以请耐心等待。我有 2 种执行不同操作的线程类型,所以我希望每个线程都有自己的互斥锁。这是我正在使用的代码,它好吗?如果不是为什么?

static pthread_mutex_t cs_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t cs_mutex2 = PTHREAD_MUTEX_INITALIZER;

void * Thread1(void * lp)
{
    int * sock = (int*)lp;
    char buffer[2024];

    int bytecount = recv(*sock, buffer, 2048, 0);
    while (0 == 0)
    {
        if ((bytecount ==0) || (bytecount == -1))
        {
        pthread_mutex_lock(&cs_mutex);

                  //Some uninteresting operations witch plays with set 1 of global variables;
        pthread_mutex_unlock(&cs_mutex);
        }
    }
}

void * Thread2(void * lp)
{   
    while (0 == 0)
    {
        pthread_mutex_lock(&cs_mutex2);
            //Some uninteresting operations witch plays with some global variables;
        pthread_mutex_unlock(&cs_mutex2);
    }
}
4

5 回答 5

7

通常,互斥锁与线程无关。它确保仅由单个线程访问关键区域。所以如果你有一些共享区域,比如多个线程处理同一个数组,那么你必须确保这个区域的独占访问。这意味着,您不需要为每个线程使用互斥锁。您需要一个用于关键区域的互斥锁。

于 2012-09-20T07:48:32.250 回答
6

如果您只有一个司机,那么拥有两辆车没有任何优势。您的Thread2代码只有在持有cs_mutex2. 因此,让多个线程运行该代码是没有意义的。一次只有一个线程可以持有互斥锁,而另一个线程不能做任何有用的工作。

所以你要做的就是偶尔不持有互斥锁的线程会尝试运行并且必须等待另一个。有时,确实持有互斥锁的线程会尝试释放并重新获取它并被另一个线程抢占。

这是完全没有意义的线程使用。

于 2012-09-20T08:06:59.027 回答
3

我在这里看到三个问题。有一个问题是你的无限循环,另一个是关于你拥有多个线程的意图,还有一个未来的可维护性“陷阱”潜伏着。

第一的

int bytecount = recv(*sock, buffer, 2048, 0);
while (0 == 0)

是对的吗?您从套接字中读取了一些内容,然后在没有关闭套接字的情况下启动了无限循环?我只能假设您在循环中进行了更多阅读,但在这种情况下,您在持有互斥锁的同时等待外部事件。一般来说,这是一种限制并发性的糟糕模式。一种可能的模式是让一个线程读取数据,然后将读取的数据传递给执行处理的其他线程。

接下来,您有两组不同的资源,每组都受自己的互斥锁保护。然后,您打算为每个资源设置一组线程。但是每个线程都有模式

   take mutex
       lots of processing
   release mutex
       tiny window (a few machine instructions)
   take mutex again
        lots of processing
   release mutex
        next tiny window

两个线程几乎没有机会并行工作。我质疑您是否需要每个资源的多个线程。

最后还有一个潜在的维护问题。我只是指出这一点以供将来参考,我认为您现在不需要做任何事情。您有两个函数,供两个线程使用,但最终它们只是任何人都可以调用的函数。如果以后的维护导致这些函数(或重构的函数子集),那么您可以获得两个线程

    take mutex 1
    take mutex 2

和另外一个

    take mutex 2
    take mutex 1

宾果游戏:僵局。

这不是一个容易避免的问题,但至少可以通过仔细的命名选择和重构来帮助维护者。

于 2012-09-20T08:18:07.390 回答
2

我认为您的代码是正确的,但请注意两点:

  1. 这不是异常安全的。如果抛出异常,Some uninteresting operations那么您的互斥锁将永远不会被解锁 -> 死锁

  2. 您还可以考虑使用 std::mutex 或 boost::mutex 代替原始互斥锁。对于互斥锁,最好使用 boost::mutex::scoped_lock (或现代编译器的 std:: 模拟)

    void test()
    {
        // not synch code here
        {
            boost::mutex::scoped_lock lock(mutex_);
            // synchronized code here
        }
    }
    
于 2012-09-20T07:35:37.180 回答
2

如果您有 2 个不同的数据集和 2 个不同的线程在这些数据集上工作——您为什么需要互斥锁?通常,当您处理一些共享数据并且您不希望两个线程同时处理它时使用互斥锁,因此您使用互斥锁锁定它,做一些事情,解锁。

于 2012-09-20T07:37:27.080 回答