需要您点亮iOS线程

问题描述

我正在数据报套接字上的POC应用程序上工作,我在iOS上。这是一个简单的单屏幕应用程序,带有几个按钮。无论如何,我的问题是EDT线程,GC线程和我的IO线程之一。我的IO线程有一个绑定的数据报套接字,等待消息(recvfrom)。有时,我发现EDT卡住了,而当我查看iOS线程堆栈时,我发现:

1-EDT线程正在睡眠,等待布尔值变为假

while(threadStateData->threadBlockedByGC) {
    usleep(1000);
}
#3  0x0000000100e6ed02 in java_lang_Thread_sleep___long at /dist/MyApplication-src/nativeMethods.m:1231
#4  0x0000000101194c44 in java_lang_System_gc__ at /dist/MyApplication-src/java_lang_System.m:257
#5  0x0000000100c431c1 in codenameoneGcMalloc at /dist/MyApplication-src/cn1_globals.m:791
#6  0x00000001011bac4a in __NEW_com_codename1_ui_Label_1 at /dist/MyApplication-src/com_codename1_ui_Label_1.m:31
#7  0x0000000101491019 in com_codename1_ui_Label___init_____java_lang_String_java_lang_String at /dist/MyApplication-src/com_codename1_ui_Label.m:1402
...

2-GC线程也处于睡眠状态,等待另一个布尔值变为真

while(t->threadActive) {
   usleep(500);
#3  0x0000000100c428d6 in codenameoneGcmark at /dist/MyApplication-src/cn1_globals.m:426
#4  0x0000000100e6e950 in java_lang_System_gcmarkSweep__ at /dist/MyApplication-src/nativeMethods.m:1078
#5  0x000000010119521d in java_lang_System_access$200__ at /dist/MyApplication-src/java_lang_System.m:331
...

A quick watch on t shows the threadId=8
t   ThreadLocalData *   0x600001616eb0  0x0000600001616eb0
threadId    JAVA_LONG   8

3-我的IO线程似乎是ID为8的线程(内存中的地址也相同)

A quick watch on threadStateData shows the threadId=8
threadStateData ThreadLocalData *   0x600001616eb0  0x0000600001616eb0
threadId    JAVA_LONG   8

ssize_t result = recvfrom(socketDescriptor,buffer,sob,(struct sockaddr *)&receiveSockaddr,&receiveSockaddrLen);

#1  0x0000000101100a00 in -[net_etc_net_impl_NativeDatagramSocketImpl receive:param1:param2:param3:] at /dist/MyApplication-src/net_et_net_impl_NativeDatagramSocketImpl.m:131
#2  0x0000000101615f6b in net_etc_net_impl_NativeDatagramSocketImplcodenameone_receive___int_int_java_lang_String_int_R_int at /dist/MyApplication-src/native_net_et_net_impl_NativeDatagramSocketImplcodenameone.m:51
#3  0x0000000100f7fc9e in net_etc_net_impl_NativeDatagramSocketStub_receive___int_int_java_lang_String_int_R_int at /dist/MyApplication-src/net_etc_net_impl_NativeDatagramSocketStub.m:87
#4  0x0000000100d59939 in virtual_net_etc_net_impl_NativeDatagramSocket_receive___int_int_java_lang_String_int_R_int at /dist/MyApplication-src/net_etc_net_impl_NativeDatagramSocket.m:91
#5  0x000000010156690f in net_etc_net_DatagramSocket_receive___byte_1ARRAY_int_R_int at /dist/MyApplication-src/net_etceterum_net_DatagramSocket.m:215

所以我的问题是:我该怎么做才能防止这种情况?

感谢您的帮助。

以马内利

解决方法

请参阅我们套接字实现中的this code。我建议在代码中添加yield / resume调用,以使GC正常工作。只要确保您在这段时间内不做任何基于Java的分配即可。

这是怎么回事:

  • GC需要运行,因此它会在所有活动线程上循环并尝试收集
  • 您的线程从Java端开始,因此被标记为GC线程
  • 它被标记为活着的
  • GC希望它暂停分配,以便可以GC
  • 线程没有意识到这一点,因为它在C代码中使用了很长时间……死锁