現狀多線程編程:在變量'iget'等於變量'iput'的情況下?
閱讀Unix套接字編程後,W.Richard史蒂芬,我正在寫一個P2P程序在主線程創建在五個子線程住線程池。然後它用kqueue()
監視50個插座。當一個事件發生在一個指定的套接字中(例如,在套接字上接收數據)時,主線程將套接字描述符複製到一個共享數組中並喚醒線程池中的一個線程。子線程然後處理來自套接字的請求。另外,我使用互斥變量和條件變量來保護共享數組。
問題
筆者提出一種在書中第30.12及30.13的源代碼「服務器/ serv08.c」和「服務器/ pthread08.c」,分別作爲如果沒有的東西這段代碼錯了。但是,當我編寫類似於一位作者的代碼片段時,線程同步效果不佳。爲什麼iput
在主線程中等於iget
?
代碼
--global變量 -
typedef struct tagThread_information
{
int sockfd;
} Thread_information;
Thread_information peer_fds[MAX_THREAD];
pthread_mutex_t peerfd_mutex;
pthread_cond_t peerfd_cond;
pthread_mutex_t STDOUT_mutex;
int iput;
int iget;
- 主thread--
void Wait_for_Handshake(download_session *pSession, int nMaxPeers)
{
struct kevent ev[50], result[50];
int kq, i, nfd;
int c = 1;
if((kq = kqueue()) == -1)
{
fprintf(stderr, "fail to initialize kqueue.\n");
exit(0);
}
for(i = 0 ; i < nMaxPeers; i++)
{
EV_SET(&ev[i], pSession->Peers[i].sockfd, EVFILT_READ, EV_ADD, 0, 0, 0);
printf("socket : %d\n", (int)ev[i].ident);
}
// create thread pool. initialize mutex and conditional variable.
iput = 0;
iget = 0;
pthread_mutex_init(&STDOUT_mutex, NULL);
pthread_mutex_init(&peerfd_mutex, NULL);
pthread_cond_init(&peerfd_cond, NULL);
// Assume that MAX_THREAD is set to 5.
for(i = 0 ; i < MAX_THREAD; i++)
thread_make(i);
while(1)
{
nfd = kevent(kq, ev, nMaxPeers, result, nMaxPeers, NULL);
if(nfd == -1)
{
fprintf(stderr, "fail to monitor kqueue. error : %d\n", errno);
nMaxPeers = Update_peer(ev, pSession->nPeers);
pSession->nPeers = nMaxPeers;
continue;
}
for(i = 0 ; i < nfd; i++)
{
pthread_mutex_lock(&peerfd_mutex);
peer_fds[iput].sockfd = (int)result[i].ident;
if(++iput == MAX_THREAD)
iput = 0;
if(iput == iget) // Here is my question.
{
exit(0);
}
pthread_cond_signal(&peerfd_cond);
pthread_mutex_unlock(&peerfd_mutex);
}
}
}
--sub thread--
void * thread_main(void *arg)
{
int connfd, nbytes;
char buf[2048];
for(; ;)
{
/* get socket descriptor */
pthread_mutex_lock(&peerfd_mutex);
while(iget == iput)
pthread_cond_wait(&peerfd_cond, &peerfd_mutex);
connfd = peer_fds[iget].sockfd;
if (++iget == MAX_THREAD)
iget = 0;
pthread_mutex_unlock(&peerfd_mutex);
/* process a request on socket descriptor. */
nbytes = (int)read(connfd, buf, 2048);
if(nbytes == 0)
{
pthread_mutex_lock(&STDOUT_mutex);
printf("\n\nthread %ld, socket : %d, nbytes : %d\n\n\n", (long int)pthread_self(), connfd, nbytes);
printf("socket closed\n\n");
pthread_mutex_unlock(&STDOUT_mutex);
close(connfd);
continue;
}
else if(nbytes == -1)
{
close(connfd);
pthread_mutex_lock(&STDOUT_mutex);
printf("\n\nthread %ld, socket : %d, nbytes : %d\n\n\n", (long int)pthread_self(), connfd, nbytes);
perror("socket error : ");
write(STDOUT_FILENO, buf, nbytes);
printf("\n\n\n\n");
pthread_mutex_unlock(&STDOUT_mutex);
continue;
}
pthread_mutex_lock(&STDOUT_mutex);
printf("\n\nthread %ld, socket : %d, nbytes : %d\n\n\n", (long int)pthread_self(), connfd, nbytes);
write(STDOUT_FILENO, buf, nbytes);
printf("\n\n\n\n");
pthread_mutex_unlock(&STDOUT_mutex);
}
}
是的,子線程可以在'iget'等於'iput'時執行。但是當'iput' =='iget'時,由於互斥操作,主線程進入睡眠狀態,對嗎?但我的主線程通過'if(iget == iput)'死掉。但作者從來沒有解釋過在主線程中通過if語句。所以我的問題是'iput'在主線程中等於'iget'嗎? – inherithandle
@inherithandle當iput == iget時,子線程進入睡眠狀態,等待條件變量。不是主線程。 –