posix多线程编程,posix线程库

  posix多线程编程,posix线程库

  多线程程序中同步访问的另一种方法是互斥,它允许程序锁定一个对象,以便只有一个线程可以访问它。为了控制对临界区代码的访问,在我们进入这段代码之前锁定一个互斥体,当我们完成操作时解锁它。

  使用互斥所需的基本函数类似于信号量所需的函数,它们的声明如下:

  #include pthread.h

  int pthread _ mutex _ init(pthread _ mutex _ t * mutex,const pthread_mutexattr_t

  * mutexattr);

  int pthread _ mutex _ lock(pthread _ mutex _ t * mutex);

  int pthread _ mutex _ unlock(pthread _ mutex _ t * mutex);

  int pthread _ mutex _ destroy(pthread _ mutex _ t * mutex);

  像往常一样,成功时返回0,失败时返回错误代码,但errno未设置;我们必须使用返回代码。

  类似于信号量,这些函数以一个指向之前声明的对象的指针作为参数,互斥的方法是pthread _ mutex _ t,额外的属性参数pthread_mutexattr_t允许我们为互斥提供属性,可以控制它的行为。该属性默认为“快速”。这有一个小缺点。如果我们的程序试图在一个已经锁定的互斥体上调用pthread_mutex_lock,程序将会阻塞。因为拥有锁的线程现在被阻塞了,互斥体将不会被解锁,程序将进入死锁状态。您可以修改互斥体的属性,这样他就可以检测到这种情况并返回一个错误,或者循环并允许在同一个线程上有多个锁。

  设置互斥属性超出了本书的范围,所以我们将为属性指针传递NULL并使用默认行为。我们可以阅读pthread_mutex_init手册页来了解修改属性的内容。

  实验线程互斥

  同样,下面的程序是我们的原始程序thread1.c的修改版本,但是做了很多修改。这一次,我们有些偏执地访问我们的关键变量,并使用一个互斥体来确保一次只有一个线程访问它们。为了使代码更容易阅读,我们忽略了对互斥锁和解锁操作返回值的错误检测。在生产代码中,我们应该检查这些返回值。这是一个新程序,thread4.c:

  #包含stdio.h

  #包含stdlib.h

  #包括unistd.h

  #包含字符串. h

  #include pthread.h

  #包含信号量. h

  void * thread _ function(void * arg);

  pthread _ mutex _ t work _ mutex

  #定义工作大小1024

  char WORK _ area[WORK _ SIZE];

  int time _ to _ exit=0;

  int main()

  {

  int res

  pthread _ t a _ thread

  void * thread _ result

  RES=pthread _ mutex _ init(work _ mutex,NULL);

  if(res!=0)

  {

  perror(互斥初始化失败);

  退出(EXIT _ FAILURE);

  }

  res=pthread_create( a_thread,NULL,thread_function,NULL);

  if(res!=0)

  {

  perror(“线程创建失败”);

  退出(EXIT _ FAILURE);

  }

  pthread _ mutex _ lock(work _ mutex);

  printf(输入一些文字,输入 end 结束/n );

  而(!离开的时间)

  {

  fgets(work_area,WORK_SIZE,stdin);

  pthread _ mutex _ unlock(work _ mutex);

  while(1)

  {

  pthread _ mutex _ lock(work _ mutex);

  if(work_area[0]!=/0)

  {

  pthread _ mutex _ unlock(work _ mutex);

  睡眠(1);

  }

  其他

  {

  打破;

  }

  }

  }

  pthread _ mutex _ unlock(work _ mutex);

  printf(/n等待线程完成./n’);

  res=pthread_join(a_thread,thread _ result);

  if(res!=0)

  {

  perror(“线程加入失败”);

  退出(EXIT _ FAILURE);

  }

  printf(螺纹连接/n );

  pthread _ mutex _ destroy(work _ mutex);

  退出(EXIT _ SUCCESS);

  }

  void *thread_function

  {

  睡眠(1);

  pthread _ mutex _ lock(work _ mutex);

  while(strncmp(end ,work_area,3)!=0)

  {

  printf(您输入了%d个字符/n ,strlen(work _ area)-1);

  work _ area[0]=/0 ;

  pthread _ mutex _ unlock(work _ mutex);

  睡眠(1);

  pthread _ mutex _ lock(work _ mutex);

  while(work_area[0]==/0 )

  {

  pthread _ mutex _ unlock(work _ mutex);

  睡眠(1);

  pthread _ mutex _ lock(work _ mutex);

  }

  }

  时间到退出=1;

  work _ area[0]=/0 ;

  pthread _ mutex _ unlock(work _ mutex);

  pthread _ exit(0);

  }

  $ cc-D _ REENTRANT-I/usr/include/nptl thread 4 . co thread 4-L/usr/lib/nptl-

  线程库

  $ ./线程4

  输入一些文本。输入“结束”结束

  一点点

  你输入4个字符

  拥挤的道路

  你输入13个字符

  目标

  正在等待线程完成.

  螺纹连接

  我们开始声明一个互斥体,我们的工作空间,这一次,我们声明了一个额外的变量:time_to_exit。

  pthread _ mutex _ t work _ mutex/*保护工作区和退出时间*/

  #定义工作大小1024

  char WORK _ area[WORK _ SIZE];

  int time _ to _ exit=0;

  然后我们初始化互斥体。

  RES=pthread _ mutex _ init(work _ mutex,NULL);

  if (res!=0) {

  perror("互斥初始化失败");

  退出(EXIT _ FAILURE);

  }

  接下来,我们开始我们的新线程。下面是在线程函数中执行的代码:

  pthread _ mutex _ lock(work _ mutex);

  while(strncmp("end ",work_area,3)!=0) {

  printf("你输入了%d个字符/n ",strlen(work _ area)-1);

  work _ area[0]=/0 ;

  pthread _ mutex _ unlock(work _ mutex);

  睡眠(1);

  pthread _ mutex _ lock(work _ mutex);

  while (work_area[0]==/0 ) {

  pthread _ mutex _ unlock(work _ mutex);

  睡眠(1);

  pthread _ mutex _ lock(work _ mutex);

  }

  }

  时间到退出=1;

  work _ area[0]=/0 ;

  pthread _ mutex _ unlock(work _ mutex);

  首先,新线程试图锁定这个互斥体。如果它已经被锁定,调用将被阻塞,直到互斥体被释放。一旦我们访问,我们检查是否我们被要求退出。如果要求我们退出,我们只需设置退出时间,清除工作区中的第一个字符,然后退出。

  如果我们不想退出,我们计算字符数,然后清空第一个字符。我们使用清除第一个字符的方法来通知读者我们已经完成了计算。然后我们解锁互斥体,等待主线程运行。我们将循环尝试锁定这个互斥体,当我们成功时,我们将检查主线程是否指定了更多的工作给我们去做。如果没有,我们解锁互斥体并等待更长的时间。如果是这样,我们计算字符数并再次进入循环。

  这里是主线:

  pthread _ mutex _ lock(work _ mutex);

  printf("输入一些文本。输入 end 结束/n ");

  而(!时间到退出){

  fgets(work_area,WORK_SIZE,stdin);

  pthread _ mutex _ unlock(work _ mutex);

  while(1) {

  pthread _ mutex _ lock(work _ mutex);

  if (work_area[0]!=/0) {

  pthread _ mutex _ unlock(work _ mutex);

  睡眠(1);

  }

  否则{

  打破;

  }

  }

  }

  pthread _ mutex _ unlock(work _ mutex);

  这类似于上面提到的线程。我们锁定工作区,以便我们可以将文本读入其中,然后解锁它以允许其他线程访问它来计算字数。循环往复,我们重新锁定互斥体,检查是否已经计算出字数,如果需要等待更长时间,我们就会释放这个锁。正如我们前面提到的,这不是一个好的编程习惯,在现实世界中,我们可以使用信号量来避免这种情况。但是,这里的代码仅用作示例。

posix多线程编程,posix线程库