while循环中的一个变量未更改,ndk/android
我是ndk的新手。你能解释一下下面的情况吗。 这是我的简单代码示例: 回路c test.cpp 在java端,我有两个带有单击侦听器的按钮:while循环中的一个变量未更改,ndk/android,android,c++,android-ndk,Android,C++,Android Ndk,我是ndk的新手。你能解释一下下面的情况吗。 这是我的简单代码示例: 回路c test.cpp 在java端,我有两个带有单击侦听器的按钮: mStart = (Button) findViewById(R.id.button1); mStop = (Button) findViewById(R.id.button2); mStart.setOnClickListener(new OnClickListener() { @Override public void onClick
mStart = (Button) findViewById(R.id.button1);
mStop = (Button) findViewById(R.id.button2);
mStart.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
exec.execute(new Runnable() {
@Override
public void run() {
Start();
}
});
}
});
mStop.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
exec.execute(new Runnable() {
@Override
public void run() {
Stop();
}
});
}
});
和服务执行人:
private Executor exec = Executors.newCachedThreadPool();
我在MSStart按下后执行启动循环。
之后,我点击mStop并等待循环停止。
但什么也没发生。
在adb控制台中,我只看到
D/TEST (17456): in the loop
D/TEST (17456): in the loop
D/TEST (17456): in the loop
..............................
D/TEST (17456): in the loop
D/TEST (17456): in the loop
信息
有人能帮我吗?如何停止循环?您的两个功能未正确同步。它们由不同的线程调用,一个线程通过单击mStart启动,另一个线程通过单击mStop启动。这本身不是问题。两个线程并行调用本机函数也不是问题。但当本机函数都试图同时访问标志时,这确实会成为一个问题 你需要同步。否则,最基本的事情可能会出错。例如,根本不能保证线程2会看到线程1中变量的更改。即使是像flag++这样的简单表达式也不再是原子表达式,可能会导致各种奇怪的效果。如果没有同步,你的应用程序就会随机化,导致崩溃
同步可以在C++和java中完成,但是对于JNI用例,通常最好将所有同步保留到java端。这只是JNI的通用软件工程指南:
尽可能使用Java,必要时使用本机在您的情况下,可能的解决方案是将循环和标志移动到java,并将JNI函数还原为C++中真正必须完成的功能。停止函数将完全用Java编写,取消标志将变成:
Start函数也将成为一个Java方法,并封装一个更简单的JNI函数:private native void print();
private void start() {
while (!cancel.get()) {
print();
}
}
void test_loop() {
__android_log_print(ANDROID_LOG_DEBUG, "TEST", "in the loop");
}
以下是简化的JNI函数:
private native void print();
private void start() {
while (!cancel.get()) {
print();
}
}
void test_loop() {
__android_log_print(ANDROID_LOG_DEBUG, "TEST", "in the loop");
}
这里有一个重要的最后提示:您可能应该使用Android SDK的类,该类专门为可取消的后台操作而设计
编辑:原始答案有一个bug。Java代码现在使用AtomicBoolean,这应该可以解决问题。编译器将在更高的优化级别将whileflag转换为while1,因为它会认为没有人在更新标志。您可以通过将标志定义为volatile来避免这种情况,这意味着有人可以从外部更新此变量
静态int标志=1;->静态易失性int标志=1 听说过锁、易失性锁、同步锁、互斥锁、信号量锁吗?那你应该知道出了什么问题。非常感谢你的帮助。这不就是僵局吗?“开始”正在执行时,您不能调用“停止”。恐怕您是对的。我最初有额外的私有同步方法,然后在发布之前对其进行了优化。我真傻。我看看今天晚些时候能不能找到答案!
private native void print();
private void start() {
while (!cancel.get()) {
print();
}
}
void test_loop() {
__android_log_print(ANDROID_LOG_DEBUG, "TEST", "in the loop");
}