我有以下代码:
int main(int argc, char** argv)
{
pthread_t thread[thr_num];
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
// just for debugging //
struct rlimit rlim;
getrlimit(RLIMIT_NPROC, &rlim);
printf ("soft = %d \n", rlim.rlim_cur);
printf ("hard = %d \n", rlim.rlim_max);
////
for ( i = 1 ; i <= thr_num ; i++) {
if(pthread_create( &thread[i], &attr, loggerThread, (void*)argv ) ) {
printf("pthread_create failure, i = %d, errno = %d \n", i, errno);
exit(1);
}
}
pthread_attr_destroy(&attr);
for ( i = 1 ; i <= thr_num ; i++) {
if( pthread_join(thread[i], (void**)&status ) ) {
exit(1);
}
}
return 0;
}
void* loggerThread(void* data)
{
char** sthg = ((char**)data);
pthread_exit(NULL);
}
我不明白为什么在thr\u num=291的情况下运行此代码时,会出现一个错误:pthread\u create failure,I=291,errno=11(EAGAIN)
使用thr_num=290工作正常。我在Linux-0.2默认值(SLES 11)上运行此代码2.6.27.54rlim.rlim_currlim.rlim_max值6906。我在“最大用户进程”的“ulimited-a”中看到了同样的情况。我还检查了pthread_create手册页引导的 /proc/sys/kernel/threads-max(它是13813)。也没有找到“sysctl-a”输出值为290的任何参数。
偶尔我从这个链接中发现:pthread_create和EAGAIN:“即使调用pthread_exit或pthread_cancel,父进程仍然需要调用pthread_join来释放pthreadID,然后它将变得可回收”
因此,作为尝试,我将我的代码修改为:
for ( i = 1 ; i <= thr_num ; i++) {
if(pthread_create( &thread[i], &attr, loggerThread, (void*)argv ) ) {
printf("pthread_create failure, i = %d, errno = %d \n", i, errno);
exit(1);
}
if( pthread_join(thread[i], (void**)&status ) ) {
printf("pthread_join failure, i = %d, errno = %d \n", i, errno);
exit(1);
}
}
pthread_attr_destroy(&attr);
然后一切都正常了:我在291循环时没有得到错误。
我想了解为什么我的原始代码会出现错误:1。因为线程2的编程错误。或者我达到了我无法识别的系统极限
也想知道我的修正是否对这个问题有好处,或者我最终用这个解决方案引入了什么隐藏的东西、陷阱?谢谢!
我最初写这篇评论,但以防万一。。。
您的代码:
for ( i = 1 ; i <= thr_num ; i++) {
if(pthread_create( &thread[i], &attr, loggerThread, (void*)argv ) ) {
printf("pthread_create failure, i = %d, errno = %d \n", i, errno);
exit(1);
}
}
...
for ( i = 1 ; i <= thr_num ; i++) {
if( pthread_join(thread[i], (void**)&status ) ) {
exit(1);
}
}
在这两个for()循环中,您都从1-thr\u num进行检查。这意味着您超出了数组线程[thr\u num]的界限,因为数组从索引0开始。因此,您应该从0迭代到小于thr\u num的1:
for ( i = 0 ; i < thr_num ; i++)
我真的很惊讶你在达到291thr_num之前没有出现分段错误。
我想了解为什么我的原始代码会出现错误:1。因为线程2的编程错误。或者我达到了我无法识别的系统极限
您可能达到了系统限制。可能您的地址空间不足。默认情况下,每个线程在linux上获得8-10Mb的堆栈空间。如果创建290个线程,将使用近3Gb的地址空间,这是32位进程的最大地址空间。
在这种情况下,您会得到EAGAIN,因为现在没有足够的资源来创建线程(因为当时没有足够的地址空间可用)。
当一个线程退出时,并不是该线程的所有资源都被释放(在linux上,整个线程堆栈都被保留)。
>
如果线程未分离,则需要对其调用pthread\u join(),以释放资源。
请注意,在循环中调用pthread\u join()的修改代码将:
也就是说,一次只有另一个线程在运行——这似乎有点毫无意义。
您当然可以生成多个并发运行的线程,但这是有限制的。在您的机器上,您似乎已经发现限制在290左右。
假设我有一些账单,上面有开始日期和结束日期。 我要检查的商业规则是 例如,3月10日到4月9日大约相隔一个月,所以我用它来检查任何两个连续的账单开始日期(4月10日和3月10日)是否相隔一个月。 现在我的问题是求周期的长度。例如,假设我有以下数据集 我正在使用JodaTime库,所以我说类似这样的话 它返回0,这是正确的,但没有用处。 结果是1,尽管相隔一天。 有什么更好的方法来做到这一点?我可以
注:本文档提供的生命周期指的是 Universal App 的生命周期,它依赖 rax-app 提供的 runApp方法。 App 级生命周期 launch 在 App 启动时触发 使用生命周期 你可以使用 rax-app 提供的 useAppLaunch 来注册 App 级别的生命周期。 示例: import { useAppLaunch } from 'rax-app'; useAppLa
我们大致为WebAPplication设计了4个生命周期: 请求初始化其实就是从URL中解析提取出{module}, {action}, {method}; 然后再根据{module}, {action}, {method}找到对应的Controller文件; 然后再调用对应的{method},完了之后再发送响应。当然响应的过程中肯定是要顺带着解析下模板标签啦。 恩,这就完了,貌似感觉很简单啊。
如下图. 可以看出,基本周期是: created mounted updated (update 可以理解成人肉手动操作触发) destroyed 上面步骤中的 1,3,4都是自动触发。 每个步骤都有对应的 beforeXyz方法 所以, 我们一般使用mounted 作为页面初始化时执行的方法
概览 组件的生命周期分为三个阶段:挂载、渲染、卸载,下图展示了解组件在整个生命周期中所涉及到的方法调用、原型方法调用和状态变化。 挂载阶段 从组件实例被创建再到被插入根组件树中,所经历的操作如下: 初始化组件实例。 根据组件类型绑定对应的原型。 调用 proto->init() 原型方法。 标记组件需要刷新全部样式。 因父组件变为另外一个组件,触发 link 事件。 更新阶段 当组件被插入到根组件
框架生命周期 Hyperf 是运行于 Swoole 之上的,想要理解透彻 Hyperf 的生命周期,那么理解 Swoole 的生命周期也至关重要。 Hyperf 的命令管理默认由 symfony/console 提供支持(如果您希望更换该组件您也可以通过改变 skeleton 的入口文件更换成您希望使用的组件),在执行 php bin/hyperf.php start 后,将由 Hyperf\Se