C 多个线程能够同时获得群集

C 多个线程能够同时获得群集,c,linux,glibc,flock,C,Linux,Glibc,Flock,我的印象是线程安全,我最近在代码中遇到过这样的情况,多个线程能够在同一个文件上获得锁,这些文件都与使用c api获得独占锁同步。进程25554是一个多线程的应用程序,它有20个线程,当死锁发生时,对同一文件具有锁的线程数会有所不同。多线程应用程序testEvent是文件的写入程序,而push是文件的读取器。不幸的是,lsof没有打印LWP值,因此我无法找到持有锁的线程。当出现下面提到的情况时,进程和线程都卡在集群调用上,如pid 25569和25554上的pstack或strace调用所示。在R

我的印象是线程安全,我最近在代码中遇到过这样的情况,多个线程能够在同一个文件上获得锁,这些文件都与使用c api获得独占锁同步。进程25554是一个多线程的应用程序,它有20个线程,当死锁发生时,对同一文件具有锁的线程数会有所不同。多线程应用程序testEvent是文件的写入程序,而push是文件的读取器。不幸的是,
lsof
没有打印LWP值,因此我无法找到持有锁的线程。当出现下面提到的情况时,进程和线程都卡在集群调用上,如pid 25569和25554上的
pstack
strace
调用所示。在RHEL 4.x中有没有关于如何克服这个问题的建议

我想更新的一件事是flock不会一直行为不端,当消息的发送速率超过2Mbps时,我才遇到flock的死锁问题,低于该发送速率,一切都是文件。我将
num_threads
=20,
size_of_msg
=1000字节保持不变,并将每秒发送的消息数从10条消息更改为100条消息,即20*1000*100=2Mbps,当我将消息数增加到150条时,就会发生群集问题

我只是想问一下你对flockfile c api的看法

 sudo lsof filename.txt
    COMMAND       PID     USER     FD       TYPE     DEVICE     SIZE   NODE       NAME
    push         25569    root     11u       REG      253.4      1079   49266853   filename.txt
    testEvent    25554    root     27uW      REG      253.4      1079   49266853   filename.txt
    testEvent    25554    root     28uW      REG      253.4      1079   49266853   filename.txt
    testEvent    25554    root     29uW      REG      253.4      1079   49266853   filename.txt
    testEvent    25554    root     30uW      REG      253.4      1079   49266853   filename.txt
调用
write\u data\u lib\u func
lib函数的多线程测试程序

void* sendMessage(void *arg)  {

int* numOfMessagesPerSecond = (int*) arg;
std::cout <<" Executing p thread id " << pthread_self() << std::endl;
 while(!terminateTest) {
   Record *er1 = Record::create();
   er1.setDate("some data");

   for(int i = 0 ; i <=*numOfMessagesPerSecond ; i++){
     ec = _write_data_lib_func(*er1);
     if( ec != SUCCESS) {
       std::cout << "write was not successful" << std::endl;

     }

   }
   delete er1;
   sleep(1);
 }

 return NULL;
void*sendMessage(void*arg){
int*nummofmessagespersecond=(int*)arg;
std::cout被记录为“如果另一个进程持有不兼容的锁,则阻塞”
对于“由flock()创建的锁与打开的文件表项相关联”,因此可以预期由同一进程的多个线程创建的
flock
-ed锁不会交互。 (flock
文档中没有提到线程)


因此,解决方案对您来说应该很简单:将一个
pthread\u mutex\u t
关联到每个
flock
可访问的文件描述符,并使用该互斥锁保护对
flock
的调用。如果您想要读写锁定,也可以使用该互斥锁。

来自flock的Linux手册页(2):

flock()创建的锁与打开的文件表项相关联。 这意味着重复的文件描述符(例如, fork(2)或dup(2))指的是同一个锁,可以使用这些描述符中的任何一个来修改或释放该锁 通过对其中任何一个执行显式锁定操作来释放 重复描述符,或当所有此类描述符都已关闭时

此外,flock锁不会“堆叠”,因此如果您试图获取已持有的锁,flock调用是一个noop,它会立即返回,而不会阻塞,也不会以任何方式更改锁状态

由于进程中的线程共享文件描述符,因此可以从不同的线程多次聚集文件,并且不会阻塞,因为锁已经被持有

也可参考关于flock(2)的注释:

flock()和fcntl(2)锁对于 分叉进程和dup(2)。在使用 fcntl(2),flock()的语义将不同于 本手册第页有详细说明


你能发布调用flock的代码吗?一个测试程序会很好。好吧,建议锁不能保证一致性。谢谢你的回答,我确信我也在考虑将互斥器与flock关联,困扰我的是flock(2)位于fcntl(2)之上,而fcntl(2)锁(2)位于fcntl(2)之上声称线程安全,所以我很惊讶这不是。我现在尝试过这个建议,有额外的pthread_mutex_t用于同步flock调用,现在发生的是19个线程在尝试获取pthread_mutex_t时被卡住,1个线程无法使用flock获得文件的独占锁,并且它被卡住了植绒(fd,锁紧);那么你从失败的flock中得到了什么错误呢?如果你看到我的lsof输出,那就不是真的了chris,文件描述符对于每个线程都是唯一的。进程中的线程共享文件描述符。请参见编辑----我想我们大多数编写多线程程序的人都编写过工作代码,在这些代码中,文件描述符是跨线程共享的线程。
for (i=0; i<_numThreads ; ++i) {
  rc = pthread_create(&threads[i], NULL, sendMessage, (void *)&_num_msgs);
  assert(0 == rc);
int write_data_lib_func(Record * rec) {      
if(fd == -1 ) {  
    fd = open(fn,O_RDWR| O_CREAT | O_APPEND, 0666);
} 
if ( fd >= 0 ) {
   /* some code */ 

   if( flock(fd, LOCK_EX) < 0 ) {
     print "some error message";
   }
   else { 
    if( maxfilesize) {
      off_t len = lseek ( fd,0,SEEK_END);
      ...
      ... 
      ftruncate( fd,0);
      ...
      lseek(fd,0,SEEK_SET); 
   } /* end of max spool size */ 
   if( writev(fd,rec) < 0 ) {
     print "some error message" ; 
   }

   if(flock(fd,LOCK_UN) < 0 ) {
   print some error message; 
   } 
int readData() {
    while(true) {
      if( fd == -1 ) {
         fd= open (filename,O_RDWR);
      }
      if( flock (fd, LOCK_EX) < 0 ) { 
        print "some error message"; 
        break; 
      } 
      if( n = read(fd,readBuf,readBufSize)) < 0 ) { 
        print "some error message" ;
        break;
      }  
      if( off < n ) { 
        if ( off <= 0 && n > 0 ) { 
          corrupt_file = true; 
        } 
        if ( lseek(fd, off-n, SEEK_CUR) < 0 ) { 
          print "some error message"; 
        } 
        if( corrupt_spool ) {  
          if (ftruncate(fd,0) < 0 ) { 
             print "some error message";
             break;
           }  
        }
      }
      if( flock(fd, LOCK_UN) < 0 ) 
       print some error message ;
      }  
   }     
}