请考虑使用互斥锁来保护数据或其他资源免受并发访问。
在 POSIX 线程的上下文中,pthread_mutex_t 类型(来自 sys/types.h, The Open Group Base Specifications Issue 7, IEEE Std 1003.1, 2013 Edition)用于互斥锁。
pthread_mutex_lock() 和 pthread_mutex_unlock() 函数 (The Open Group Base Specifications Issue 7, IEEE Std 1003.1, 2013 Edition) 可用于保护链表类型的实例免受两个操作的并发访问:
- 读取操作:枚举列表时(即读取
next指针)并使用(读取/写入)存储在节点中的数据;
- 写入操作:更改节点:
next 指针和存储在节点中的数据。
此外,相同的互斥锁可用于保护对head [链表] 指针的访问。
例子:
// ...
pthread_mutex_t list_mutex = PTHREAD_MUTEX_INITIALIZER;
// ...
void *peer_handler(void *p)
{
// ...
pthread_mutex_lock(&list_mutex);
if (numNodes == 0) {
head = newNode;
tail = newNode;
tail->next = NULL;
numNodes++;
}
else {
tail->next = newNode;
tail = newNode;
tail->next = NULL;
numNodes++;
}
pthread_mutex_unlock(&list_mutex);
// ...
pthread_mutex_lock(&list_mutex);
struct fileNode *ptr = head;
while (ptr != NULL) {
if ((strcmp(ptr->ip, temp_ip) == 0) && ptr->port == temp_port) {
cmd = htonl(200);
break;
}
ptr = ptr->next;
}
pthread_mutex_unlock(&list_mutex);
// ...
}
void sendList(int newsockfd)
{
// ...
pthread_mutex_lock(&list_mutex);
struct fileNode *ptr;
ptr = head;
while (ptr != NULL) {
// ...
ptr = ptr->next;
// ...
}
pthread_mutex_unlock(&list_mutex);
}
void removeFiles(uint32_t port, char *client_ip)
{
pthread_mutex_lock(&list_mutex);
// ...
pthread_mutex_unlock(&list_mutex);
}
void print()
{
// ...
pthread_mutex_lock(&list_mutex);
struct fileNode *ptr;
ptr = head;
while (ptr != NULL) {
// ...
ptr = ptr->next;
// ...
}
pthread_mutex_unlock(&list_mutex);
}
值得注意的是,减少锁争用是优化并发应用程序性能的重要部分。
套接字相关问题
send() 和 recv() 函数不保证所有指定的字节数将通过一次函数调用发送/接收。
应使用适当的循环来发送或接收所需(预期)字节数。更多详情请参考文章:TCP/IP client-server application: exchange with string messages。
此外,请注意此类结构:
n = recv(newsockfd, buffer, sizeof(buffer), 0);
// ...
buffer[n] = '\0';
要接收的预期字节数(或在本例中为字符)应为sizeof(buffer) - 1。否则,会丢失数据:最后一个字符被终止的空字符覆盖。