首页 > 其他分享 >pthread_once导致死锁

pthread_once导致死锁

时间:2024-08-06 23:49:38浏览次数:18  
标签:__ control val PTHREAD 死锁 pthread once

在一个pthread_once方法内又再次调用了这个pthread_once导致死锁。

分析下这个pthread_once的源码:


可以看到这个pthread_once_t结构体就是一个整形数字加自旋锁。

int
___pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
{
  /* Fast path.  See __pthread_once_slow.  */
  int val;
  val = atomic_load_acquire (once_control);
  if (__glibc_likely ((val & __PTHREAD_ONCE_DONE) != 0)) // 这里判断如果已经执行完成就返回0
    return 0;
  else
    return __pthread_once_slow (once_control, init_routine);
}
static int
__attribute__ ((noinline))
__pthread_once_slow (pthread_once_t *once_control, void (*init_routine) (void))
{
  while (1)
    {
      int val, newval;

      /* CAS把状态改为__PTHREAD_ONCE_INPROGRESS */
      /* We need acquire memory order for this load because if the value
         signals that initialization has finished, we need to see any
         data modifications done during initialization.  */
      val = atomic_load_acquire (once_control);
      do
	{
	  /* Check if the initialization has already been done.  */
	  if (__glibc_likely ((val & __PTHREAD_ONCE_DONE) != 0))
	    return 0;

	  /* We try to set the state to in-progress and having the current
	     fork generation.  We don't need atomic accesses for the fork
	     generation because it's immutable in a particular process, and
	     forked child processes start with a single thread that modified
	     the generation.  */
	  newval = __fork_generation | __PTHREAD_ONCE_INPROGRESS;
	  /* We need acquire memory order here for the same reason as for the
	     load from once_control above.  */
	}
      while (__glibc_unlikely (!atomic_compare_exchange_weak_acquire (
	  once_control, &val, newval)));

      /* Check if another thread already runs the initializer.	*/
      if ((val & __PTHREAD_ONCE_INPROGRESS) != 0)
	{
       /* 修改失败,说明其他线程在修改,直接等待 */
	  /* Check whether the initializer execution was interrupted by a
	     fork.  We know that for both values, __PTHREAD_ONCE_INPROGRESS
	     is set and __PTHREAD_ONCE_DONE is not.  */
	  if (val == newval)
	    {
	      /* Same generation, some other thread was faster.  Wait and
		 retry.  */
	      futex_wait_simple ((unsigned int *) once_control,
				 (unsigned int) newval, FUTEX_PRIVATE);
	      continue;
	    }
	}

      /* This thread is the first here.  Do the initialization.
	 Register a cleanup handler so that in case the thread gets
	 interrupted the initialization can be restarted.  */
      pthread_cleanup_combined_push (clear_once_control, once_control);
      /* 调用用户传入的方法 */
      init_routine ();

      pthread_cleanup_combined_pop (0);


      /* Mark *once_control as having finished the initialization.  We need
         release memory order here because we need to synchronize with other
         threads that want to use the initialized data.  */
      /* 修改状态为__PTHREAD_ONCE_DONE */
      atomic_store_release (once_control, __PTHREAD_ONCE_DONE);

      /* Wake up all other threads.  */
      /* 唤醒其他线程 */
      futex_wake ((unsigned int *) once_control, INT_MAX, FUTEX_PRIVATE);
      break;
    }

  return 0;
}

标签:__,control,val,PTHREAD,死锁,pthread,once
From: https://www.cnblogs.com/yghr/p/18346200

相关文章

  • 【多线程-从零开始-肆】线程安全、加锁和死锁
    进程状态进程状态:就绪:正在CPU上执行,或者随时可以去CPU上执行阻塞:暂时不能参与CPU的执行Java的线程,对应状态做了更详细的区分,不仅仅是就绪和阻塞了六种状态:NEW当前Thread对象虽然有了,但是内核的线程还没有(还没调用过start)TERMINATE当前Thread对......
  • 第六章 死锁
    第六章死锁6.1资源资源就是随着时间的推移,必须能获得、使用以及释放的任何东西。6.1.1可抢占资源和不可抢占资源资源分为两类:可抢占的和不可抢占的。可抢占资源(preemptableresource)可以从拥有它的进程中抢占而不会产生任何副作用,存储器就是一类可抢占的资源。......
  • ffmpeg python 导致死锁
    我在使用ffmpegpython处理相机帧时遇到问题。我使用process.communicate()的第一种方法效果很好,但存在延迟问题。process=(ffmpeg.input('pipe:',format='rawvideo',pix_fmt='rgb24',s='{}x{}'.format(width,height))......
  • 【MySQL(锁篇)】深入MySQL锁机制:从全局到行级,解锁数据库性能瓶颈(下:行锁分析实战、死锁原
    文章目录MySQL(锁篇)-全局锁、表锁、行锁(记录锁、间隙锁、临键锁、插入意向锁)、意向锁、SQL加锁分析、死锁产生原因与排查行锁分析实战1读已提交RC1.1组合一:ID是主键1.2组合二:ID唯一索引1.3组合三:ID非唯一索引1.4组合四:ID无索引2可重复读RR2.1组合五:ID主键2.2组......
  • C++ - VS2019配置pthread线程库
    1.说明在VS里用MS编译器不能直接调用pthread库,需要先自行下载该库:http://sourceware.org/pub/pthreads-win32/pthreads-w32-2-9-1-release.zip解压后用得到的只有Pre-built.2文件夹下的文件。2.配置如下图分别配置三大项:包含目录-->...pthreads-w32-2-9-1-release\Pre-bu......
  • OncePower,让你的文件重命名变得像呼吸一样简单!
    ......
  • JavaEE 初阶(7)——多线程5之线程安全中 -->“死锁”
    目录一.什么是“死锁”二.产生死锁的场景  场景1:一个线程连续加锁 场景2:两个线程两把锁场景3:N个线程M把锁 三.产生死锁的四个必要条件(缺一不可)四. Java标准库中的线程安全类一.什么是“死锁”并非是synchronized就一定线程安全,还要看代码具体咋写。到底......
  • MySQL PXC 集群死锁分析案例
    前不久一个系统死锁导致部分业务受到影响,今次补上详细的节点日志分析过程。这个PXC集群有三个节点,分别是108、109、110,日志信息的ip6地址、节点编号等信息均已做脱敏处理。以下日志里面,3个节点对应的配置信息是:10899999999-99089999:9999:9999:9999::6c10999999999-99099......
  • Linux获取线程调度策略pthread_attr_getschedpolicy
    thread_attr_getschedpolicy 函数是POSIX线程(pthread)库中用于获取线程属性对象中的调度策略的函数。在实时系统中,调度策略决定了线程如何被调度器选择来执行。pthread_attr_getschedpolicy 函数允许你查询一个已创建的线程属性对象(pthread_attr_t 类型)中设置的调度策略......
  • 死锁-举例
    首先回顾我们对死锁的定义,通俗易懂地说就是双方在占有自己手上的资源时,需要对方手上的资源才能继续下去,但是双方又不愿意主动放弃自己手上的资源用一个生活中通俗易懂的例子就是:对方道歉我就道歉这个模型用代码实现最简单的框架是这样publicclassMustDeadLockimplementsRun......